jdk1.7.0_79
Im vorherigen Artikel „ThreadPoolExecutor-Thread Das Prinzip des Thread-Pools ThreadPoolExecutor und seine Ausführungsmethode werden im Abschnitt „Pool-Prinzip und seine Ausführungsmethode“ erwähnt. Dieser Artikel analysiert ThreadPoolExecutor#submit.
Für die Ausführung einer Aufgabe benötigen wir manchmal keine Ergebnisse, aber es gibt Zeiten, in denen wir Ausführungsergebnisse zurückgeben müssen. Wenn ein Thread kein Ergebnis zurückgeben muss, kann er Runnable implementieren, und wenn er das Ergebnis ausführen muss, kann er Callable implementieren. Im Thread-Pool stellt Execute auch eine Aufgabenausführung bereit, die keine Ergebnisse zurückgeben muss, und für diejenigen, die Ergebnisse zurückgeben müssen, kann die Submit-Methode aufgerufen werden.
Überprüfen Sie die Vererbungsbeziehung von ThreadPoolExecutor.
Nur die Ausführungsmethode ist in der Executor-Schnittstelle definiert, während die Submit-Methode in der ExecutorService-Schnittstelle definiert ist.
//ExecutorServicepublic interface ExecutorService extends Executor { ... <T> Future<T> submit(Callable<T> task); <T> Future<T> submit(Runnable task, T result); <T> Future<T> submit(Runnable task); ... }
Die Submit-Methode ist in ihrer Unterklasse AbstractExecutorService implementiert.
//AbstractExecutorServicepublic abstract class AbstractExecutorService implements ExecutorService { ... public <T> Future<T> submit(Callable<T> task) { if (task == null) throw new NullPointerException(); RunnableFuture<T> ftask = newTaskFor(task); execute(ftask); return ftask; } public <T> Future<T> submit(Runnable task, T result) { if (task == null) throw new NullPointerException(); RunnableFuture<T> ftask = newTaskFor(task); execute(ftask); return ftask; } public Future<?> submit(Runnable task) { if (task == null) throw new NullPointerExeption(); RunnableFuture<Void> ftask = newTaskFor(task, null); execute(ftask); return ftask; } ... }
Die in AbstractExecutorService implementierte Submit-Methode ist eigentlich eine Vorlagenmethode, die das Algorithmusgerüst der Submit-Methode definiert und deren Ausführung an die Unterklasse übergeben wird. (Es ist ersichtlich, dass in vielen Quellcodes das Vorlagenmethodenmuster weit verbreitet ist. Informationen zum Vorlagenmethodenmuster finden Sie unter „Vorlagenmethodenmuster“)
Obwohl die Submit-Methode den Rückgabewert von bereitstellen kann Thread-Ausführung, nur Callable wird implementiert. Es wird einen Rückgabewert geben, aber der Thread, der Runnable implementiert, hat keinen Rückgabewert. Das heißt, unter den oben genannten drei Methoden kann subscribe(Callable
Nachfolgend finden Sie drei Beispiele, um ein Gefühl für die Absendemethode zu bekommen.
submit(Callable
package com.threadpoolexecutor;import java.util.concurrent.*;/** * ThreadPoolExecutor#sumit(Callable<T> task) * Created by yulinfeng on 6/17/17. */public class Sumit1 {public static void main(String[] args) throws ExecutionException, InterruptedException { Callable<String> callable = new Callable<String>() {public String call() throws Exception { System.out.println("This is ThreadPoolExetor#submit(Callable<T> task) method.");return "result"; } }; ExecutorService executor = Executors.newSingleThreadExecutor(); Future<String> future = executor.submit(callable); System.out.println(future.get()); } }
submit(Runnable Aufgabe, T-Ergebnis)
package com.threadpoolexecutor;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;/** * ThreadPoolExecutor#submit(Runnable task, T result) * Created by yulinfeng on 6/17/17. */public class Submit2 {public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService executor = Executors.newSingleThreadExecutor(); Data data = new Data(); Future<Data> future = executor.submit(new Task(data), data); System.out.println(future.get().getName()); } }class Data { String name;public String getName() {return name; }public void setName(String name) {this.name = name; } }class Task implements Runnable { Data data;public Task(Data data) {this.data = data; }public void run() { System.out.println("This is ThreadPoolExetor#submit(Runnable task, T result) method."); data.setName("kevin"); } }
submit(Ausführbare Aufgabe)
package com.threadpoolexecutor;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;/** * ThreadPoolExecutor#sumit(Runnable runnables) * Created by yulinfeng on 6/17/17. */public class Submit {public static void main(String[] args) throws ExecutionException, InterruptedException { Runnable runnable = new Runnable() {public void run() { System.out.println("This is ThreadPoolExetor#submit(Runnable runnable) method."); } }; ExecutorService executor = Executors.newSingleThreadExecutor(); Future future = executor.submit(runnable); System.out.println(future.get()); } }
Aus dem obigen Beispiel können Sie ersehen, dass beim Aufruf von subscribe(Runnable runnable) der definierte Typ nicht erforderlich ist, obwohl er in AbstractExecutorService als generische Methode definiert ist ist keine generische Methode, da sie keinen Rückgabewert hat. (Informationen zu den Unterschieden zwischen Object, T und ? finden Sie unter „Der Unterschied zwischen Object, T (Generics) und ? in Java“).
Wie Sie dem obigen Quellcode entnehmen können, sind diese drei Methoden fast gleich. Der Schlüssel liegt in:
RunnableFuture<T> ftask = newTaskFor(task); execute(ftask);
Wie eine Aufgabe ausgeführt wird ein Parameter Wie wäre es, wenn Sie ihn an newTaskFor übergeben, dann die Ausführungsmethode aufrufen und schließlich ftask zurückgeben?
//AbstractExecutorService#newTaskForprotected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) { return new FutureTask<T>(callable); } protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) { return new FutureTask<T>(runnable, value); }
Es scheint, dass eine FutureTask-Instanz zurückgegeben wird und FutureTask die Future- und Runnable-Schnittstellen implementiert. Die Future-Schnittstelle ist eine Implementierung des Java-Thread-Future-Modus, der für asynchrone Berechnungen verwendet werden kann. Die Implementierung der Runnable-Schnittstelle bedeutet, dass sie als Thread ausgeführt werden kann. FutureTask implementiert diese beiden Schnittstellen, was bedeutet, dass es das Ergebnis einer asynchronen Berechnung darstellt und als Thread zur Ausführung an den Executor übergeben werden kann. FutureTask wird im nächsten Kapitel separat analysiert. Daher ist die Analyse der Submit-Methode des Thread-Pools ThreadPoolExecutor in diesem Artikel nicht vollständig. Sie müssen den Future-Modus von Java-Threads verstehen – „14. Future-Modus in Java“.
Das obige ist der detaillierte Inhalt vonSubmit-Methode des ThreadPoolExecutor-Thread-Pools. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!