Heim >Java >javaLernprogramm >Detaillierte Code-Erklärung von Callable und Future im Java-Parallelitäts-Thread-Pool

Detaillierte Code-Erklärung von Callable und Future im Java-Parallelitäts-Thread-Pool

黄舟
黄舟Original
2017-06-18 10:11:141585Durchsuche

In diesem Artikel werden hauptsächlich Callable und Future of Java-Parallelitäts-Thread-Pools ausführlich vorgestellt, die einen bestimmten Referenzwert haben:

Einführung in Callable and Future

Callable und Future sind eine interessante Kombination. Wir müssen sie verwenden, wenn wir die Ausführungsergebnisse des Threads erhalten müssen. Callable wird verwendet, um Ergebnisse zu erzeugen, und Future wird verwendet, um Ergebnisse zu erhalten.

1. Callable

Callable ist eine Schnittstelle, die nur eine call()-Methode enthält. Ein Callable ist eine Aufgabe, die ein Ergebnis zurückgibt und möglicherweise eine Ausnahme auslöst.
Um das Verständnis zu erleichtern, können wir Callable mit einer Runnable-Schnittstelle vergleichen, und die call()-Methode von Callable ähnelt der run()-Methode von Runnable.
Der Quellcode von Callable lautet wie folgt:


public interface Callable<V> {
 V call() throws Exception;
}

Erklärung: Davon haben wir Sie können sehen, dass Callable Generics unterstützt.

2. Zukunft

Zukunft ist eine Schnittstelle. Es wird verwendet, um die Ergebnisse asynchroner Berechnungen darzustellen. Es werden Methoden bereitgestellt, um zu überprüfen, ob die Berechnung abgeschlossen ist, um auf den Abschluss der Berechnung zu warten und um das Ergebnis der Berechnung zu erhalten. Der Quellcode von
Future lautet wie folgt:


public interface Future<V> {
 // 试图取消对此任务的执行。
 boolean cancel(boolean mayInterruptIfRunning)

 // 如果在任务正常完成前将其取消,则返回 true。
 boolean isCancelled()

 // 如果任务已完成,则返回 true。
 boolean isDone()

 // 如有必要,等待计算完成,然后获取其结果。
 V  get() throws InterruptedException, ExecutionException;

 // 如有必要,最多等待为使计算完成所给定的时间之后,获取其结果(如果结果可用)。
 V  get(long timeout, TimeUnit unit)
  throws InterruptedException, ExecutionException, TimeoutException;
}

Erklärung: Future wird zur Darstellung des verwendet Ergebnisse asynchroner Berechnungen. Seine Implementierungsklasse ist FutureTask. Bevor wir FutureTask erklären, schauen wir uns zunächst das Beziehungsdiagramm zwischen Callable, Future und FutureTask wie folgt an:

Beschreibung:

(01) RunnableFuture ist eine Schnittstelle, die die beiden Schnittstellen Runnable und Future erbt. Der Quellcode von RunnableFuture lautet wie folgt:


public interface RunnableFuture<V> extends Runnable, Future<V> {
 void run();
}

(02) FutureTask implementiert die RunnableFuture-Schnittstelle. Daher sagen wir auch, dass es die Future-Schnittstelle implementiert.

Beispiel und Quellcode-Analyse (basierend auf JDK1.7.0_40)

Sehen wir uns zunächst die grundlegende Verwendung von Callable und Future anhand eines Beispiels an Analysieren Sie dann das Beispielimplementierungsprinzip.


import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ExecutionException;

class MyCallable implements Callable {

 @Override 
 public Integer call() throws Exception {
 int sum = 0;
 // 执行任务
 for (int i=0; i<100; i++)
  sum += i;
 //return sum; 
 return Integer.valueOf(sum);
 } 
}

public class CallableTest1 {

 public static void main(String[] args) 
 throws ExecutionException, InterruptedException{
 //创建一个线程池
 ExecutorService pool = Executors.newSingleThreadExecutor();
 //创建有返回值的任务
 Callable c1 = new MyCallable();
 //执行任务并获取Future对象 
 Future f1 = pool.submit(c1);
 // 输出结果
 System.out.println(f1.get()); 
 //关闭线程池 
 pool.shutdown(); 
 }
}

Laufergebnis:

4950

Ergebnisbeschreibung:

Erstellen Sie im Haupt-Thread main einen neuen Thread-Pool über newSingleThreadExecutor(). Erstellen Sie dann das aufrufbare Objekt c1, senden Sie c1 zur Verarbeitung über pool.submit (c1) an den Thread-Pool und speichern Sie das zurückgegebene Ergebnis im zukünftigen Objekt f1. Dann erhalten wir die in Callable gespeicherten Ergebnisse über f1.get(); schließlich schließen wir den Thread-Pool über pool.shutdown().

1. subscribe()

submit() ist in java/util/concurrent/AbstractExecutorService.java implementiert folgt:


public <T> Future<T> submit(Callable<T> task) {
 if (task == null) throw new NullPointerException();
 // 创建一个RunnableFuture对象
 RunnableFuture<T> ftask = newTaskFor(task);
 // 执行“任务ftask”
 execute(ftask);
 // 返回“ftask”
 return ftask;
}

Erklärung: subscribe() erstellt das RunnableFuture-Objekt ftask über newTaskFor(task). Der Quellcode lautet wie folgt:


protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
 return new FutureTask<T>(callable);
}

2. FutureTasks Konstruktor

Der Konstruktor von FutureTask lautet wie folgt:


public FutureTask(Callable<V> callable) {
 if (callable == null)
 throw new NullPointerException();
 // callable是一个Callable对象
 this.callable = callable;
 // state记录FutureTask的状态
 this.state = NEW; // ensure visibility of callable
}

3. Die run()-Methode von FutureTask

Kommen wir zurück zum Quellcode vonsubmit().
Nachdem newTaskFor() ein Ftask-Objekt erstellt hat, wird die Aufgabe über Execute(ftask) ausgeführt. Zu diesem Zeitpunkt wird ftask als ausführbares Objekt ausgeführt und seine run()-Methode wird schließlich aufgerufen. Die run()-Methode von ftask ist in java/util/concurrent/FutureTask.java implementiert und der Quellcode lautet wie folgt :


public void run() {
 if (state != NEW ||
 !UNSAFE.compareAndSwapObject(this, runnerOffset,
     null, Thread.currentThread()))
 return;
 try {
 // 将callable对象赋值给c。
 Callable<V> c = callable;
 if (c != null && state == NEW) {
  V result;
  boolean ran;
  try {
  // 执行Callable的call()方法,并保存结果到result中。
  result = c.call();
  ran = true;
  } catch (Throwable ex) {
  result = null;
  ran = false;
  setException(ex);
  }
  // 如果运行成功,则将result保存
  if (ran)
  set(result);
 }
 } finally {
 runner = null;
 // 设置“state状态标记”
 int s = state;
 if (s >= INTERRUPTING)
  handlePossibleCancellationInterrupt(s);
 }
}

Erklärung: run() führt die call()-Methode des Callable-Objekts aus und schließlich Speichern Sie das Ergebnis unter result. Speichern Sie das Ergebnis über set(result).
  Nach dem Aufruf der get()-Methode von FutureTask wird der von set(result) gespeicherte Wert zurückgegeben.

Das obige ist der detaillierte Inhalt vonDetaillierte Code-Erklärung von Callable und Future im Java-Parallelitäts-Thread-Pool. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn