అమలు చేయగల సమస్య
రన్ చేయదగిన ఇంటర్ఫేస్ మరియు దానిని అమలు చేసే థ్రెడ్ క్లాస్తో మీకు ఇప్పటికే సుపరిచితమే . ఈ ఇంటర్ఫేస్ ఎలా ఉంటుందో గుర్తుచేసుకుందాం:
public interface Runnable {
public abstract void run();
}
రన్ పద్ధతి యొక్క రిటర్న్ రకం శూన్యం అని గమనించండి . కానీ మన థ్రెడ్ దాని పని యొక్క కొంత ఫలితాన్ని సంఖ్య, స్ట్రింగ్ లేదా ఏదైనా ఇతర వస్తువు రూపంలో తిరిగి ఇవ్వాల్సిన అవసరం ఉంటే ఏమి చేయాలి? అప్పుడు మనం ఒక పరిష్కారాన్ని తీసుకురావాలి. ఇలాంటిది ఏదైనా:
public class Fibonacci implements Runnable {
private final int index;
private int result;
public Fibonacci(int index) {
this.index = index;
}
@Override
public void run() {
int first = 0;
int second = 1;
if (index == 1) {
result = first;
} else if (index == 2) {
result = second;
} else {
for (int i = 0; i < index - 2; i++) {
int temp = second;
second += first;
first = temp;
}
result = second;
}
}
public static void printByIndex(int index) throws InterruptedException {
Fibonacci fibonacci = new Fibonacci(index);
Thread thread = new Thread(fibonacci);
thread.start();
thread.join();
System.out.println("Fibonacci number " + index + ": " + fibonacci.result);
}
}
కింది ప్రధాన పద్ధతిని అమలు చేద్దాం :
public static void main(String[] args) throws Exception {
Fibonacci.printByIndex(10);
}
కన్సోల్ ప్రదర్శిస్తుంది:
ఈ కోడ్ అనేక లోపాలను కలిగి ఉంది. ఉదాహరణకు, చేరడం పద్ధతికి కాల్ ఫలితంగా , printByIndex పద్ధతిని అమలు చేస్తున్నప్పుడు ప్రధాన థ్రెడ్ బ్లాక్ చేయబడుతుంది .
కాల్ చేయగల ఇంటర్ఫేస్
ఇప్పుడు Java మనకు అందించే ఇంటర్ఫేస్ని చూద్దాం, ఇది Runnable కి ప్రత్యామ్నాయంగా ఉపయోగించవచ్చు . ఇది కాల్ చేయగల ఇంటర్ఫేస్:
public interface Callable<V> {
V call() throws Exception;
}
మీరు చూడగలిగినట్లుగా, Runnable వలె , దీనికి ఒకే ఒక పద్ధతి ఉంది. ఈ పద్ధతి రన్ పద్ధతి వలె అదే ప్రయోజనాన్ని అందిస్తుంది - ఇది సమాంతర థ్రెడ్లో అమలు చేయబడే కోడ్ను కలిగి ఉంటుంది. తేడాల విషయానికొస్తే, తిరిగి వచ్చే విలువను పరిశీలించండి. ఇప్పుడు ఇంటర్ఫేస్ని అమలు చేస్తున్నప్పుడు మీరు పేర్కొన్న ఏ రకం అయినా కావచ్చు:
public class CurrentDate implements Callable<Long> {
@Override
public Long call() {
return new Date().getTime();
}
}
మరొక ఉదాహరణ:
Callable<String> task = () -> {
Thread.sleep(100);
return "Done";
};
ఇక్కడ ఉపయోగకరమైనది మరొకటి ఉంది — కాల్ పద్ధతి మినహాయింపును ఇవ్వగలదు . అంటే, రన్ పద్ధతి వలె కాకుండా, కాల్ పద్ధతిలో మేము పద్ధతి లోపల సంభవించే తనిఖీ చేయబడిన మినహాయింపులను నిర్వహించాల్సిన అవసరం లేదు:
|
|
భవిష్యత్ ఇంటర్ఫేస్
కాల్ చేయదగినదితో సన్నిహితంగా పనిచేసే మరొక ఇంటర్ఫేస్ ఫ్యూచర్ . ఫ్యూచర్ అసమకాలిక (సమాంతర) గణనల ఫలితాన్ని సూచిస్తుంది ( కాల్ పద్ధతి ద్వారా అందించబడిన విలువ). ఇది గణనలు పూర్తయ్యాయో లేదో తనిఖీ చేయడానికి, లెక్కలు పూర్తయ్యే వరకు వేచి ఉండటానికి, గణనల ఫలితాన్ని పొందడానికి మరియు మరిన్నింటిని అనుమతిస్తుంది.
ఫ్యూచర్ ఇంటర్ఫేస్ యొక్క పద్ధతులు
-
boolean isDone() — ఈ పని (గణన) పూర్తి అయినట్లయితే ఈ పద్ధతి నిజమైనదిగా చూపబడుతుంది. సాధారణంగా ముగిసిన, మినహాయింపుతో ముగిసిన లేదా రద్దు చేయబడిన పనులు పూర్తయినట్లుగా పరిగణించబడతాయి.
-
V get() — అవసరమైతే, ఈ పద్ధతి దానిని పిలిచిన థ్రెడ్ను బ్లాక్ చేస్తుంది మరియు అవి పూర్తయినప్పుడు గణనల ఫలితాన్ని అందిస్తుంది.
-
V get(దీర్ఘ సమయం ముగిసింది, టైమ్యూనిట్ యూనిట్) — మునుపటి పద్ధతి వలె, ఈ పద్ధతి దానిని పిలిచిన థ్రెడ్ను బ్లాక్ చేస్తుంది, ఫలితం కోసం వేచి ఉంది, కానీ పద్ధతి పారామితుల ద్వారా పేర్కొన్న సమయానికి మాత్రమే.
-
బూలియన్ రద్దు (బూలియన్ మేఇంటర్రప్ట్ఇఫ్రన్నింగ్) — ఈ పద్ధతి పనిని అమలు చేయడాన్ని ఆపడానికి ప్రయత్నిస్తుంది. టాస్క్ ఇంకా పనిచేయడం ప్రారంభించకపోతే, అది ఎప్పటికీ అమలు కాదు. టాస్క్ ప్రోగ్రెస్లో ఉంటే, అప్పుడు mayInterruptIfRunning పరామితి టాస్క్ని అమలు చేస్తున్న థ్రెడ్కు అంతరాయం కలిగించే ప్రయత్నం జరుగుతుందో లేదో నిర్ణయిస్తుంది. రద్దు పద్ధతిని పిలిచిన తర్వాత , isDone పద్ధతి ఎల్లప్పుడూ నిజమైనదిగా చూపబడుతుంది .
-
boolean isCancelled() — ఇది సాధారణంగా పూర్తి కావడానికి ముందు పని రద్దు చేయబడితే ఈ పద్ధతి నిజమని చూపుతుంది. రద్దు పద్ధతిని మునుపు పిలిచి, ఒప్పు అని తిరిగి ఇచ్చినట్లయితే, పద్ధతి ఎల్లప్పుడూ నిజమైనదిగా చూపబడుతుంది .
కాల్ చేయదగిన మరియు ఫ్యూచర్ ఉపయోగించి కోడ్ యొక్క ఉదాహరణ
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;
public class Fibonacci implements Callable<Integer> {
private final int index;
public Fibonacci(int index) {
this.index = index;
}
@Override
public Integer call() {
int first = 0;
int second = 1;
if (index == 1) {
return first;
} else if (index == 2) {
return second;
} else {
for (int i = 0; i < index - 2; i++) {
int temp = second;
second += first;
first = temp;
}
return second;
}
}
public static Future<Integer> calculateAsync(int index) throws Exception {
Fibonacci fibonacci = new Fibonacci(index);
// The future object will represent the result of running the fibonacci task.
FutureTask<Integer> future = new FutureTask<>(fibonacci);
// Because the FutureTask class implements both the Future interface and the Runnable interface,
// you can pass instances of it to the Thread constructor
Thread thread = new Thread(future);
thread.start();
return future;
}
}
కింది ప్రధాన పద్ధతిని అమలు చేద్దాం :
public static void main(String[] args) throws Exception {
Map<Integer, Future<Integer>> tasks = new HashMap<>();
for (int i = 10; i < 20; i++) {
tasks.put(i, Fibonacci.calculateAsync(i));
}
for (Map.Entry<Integer, Future<Integer>> entry : tasks.entrySet()) {
Future<Integer> task = entry.getValue();
int index = entry.getKey();
int result;
// Check whether the task is done
if (task.isDone()) {
// Get the result of the calculations
result = task.get();
} else {
try {
// Wait another 100 milliseconds for the result of the calculations
result = task.get(100, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
// Interrupt the task
task.cancel(true);
System.out.println("Fibonacci number " + index + " could not be calculated in the allotted time.");
return;
}
}
System.out.println("Fibonacci number " + index + ": " + result);
}
}
కన్సోల్ ప్రదర్శిస్తుంది:
ఫిబొనాక్సీ నంబర్ 17: 987
ఫిబొనాక్సీ నంబర్ 18: 1597
ఫిబొనాక్సీ నంబర్ 19: 2584
ఫిబొనాక్సీ నంబర్ 10: 34
ఫిబొనాక్సీ నంబర్ 11: 55
ఫిబొనాక్సీ నంబర్ 12
: ఫిబొనాక్సీ నంబర్ 12
: 849 233
ఫైబొనాక్సీ సంఖ్య 15: 377
GO TO FULL VERSION