


Die Beziehung und Verwendung zwischen Future und FutureTask in Java (mit Code)
Der Inhalt dieses Artikels befasst sich mit der Beziehung und Verwendung zwischen Future und FutureTask in Java (mit Code). Ich hoffe, dass er für Sie hilfreich ist. .
Future und FutureTask werden beide verwendet, um die Rückgabeergebnisse der Thread-Ausführung zu erhalten. Im Folgenden geben wir eine allgemeine Einführung und Analyse der Beziehung und Verwendung zwischen den beiden
1. Future und Einführung in FutureTask:
Future befindet sich unter dem Paket java.util.concurrent, es ist eine Schnittstelle
public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; }
In der Future-Schnittstelle sind 5 Methoden deklariert. Die Funktion jeder Methode wird unten vorgestellt:
Die Abbruchmethode wird verwendet, um die Aufgabe abzubrechen. Sie gibt „true“ zurück, wenn der Abbruch erfolgreich ist scheitert. Der Parameter mayInterruptIfRunning ist auf false gesetzt, was bedeutet, dass eine Unterbrechung während der Ausführung des Threads nicht zulässig ist, und auf true, was bedeutet, dass eine Unterbrechung zulässig ist. Konkret kann es in die folgenden drei Situationen unterteilt werden:
1. Wenn die Aufgabe abgeschlossen wurde, unabhängig davon, ob mayInterruptIfRunning wahr oder falsch ist, wird false zurückgegeben. Dies liegt daran, dass die Aufgabe, die Sie abbrechen möchten, abgeschlossen wurde abgeschlossen und der Aufgabenabbruch gilt als fehlgeschlagen ;
2. Wenn die Aufgabe ausgeführt wird, wird true zurückgegeben, unabhängig davon, ob mayInterruptIfRunning true oder false ist. Es ist nur so, dass der Thread unterbrochen wird, wenn mayInterruptIfRunning wahr ist, und wenn es falsch ist, wird der Thread nicht unterbrochen und die Ausführung abgeschlossen.
3. Wenn die Aufgabe nicht ausgeführt wurde, unabhängig davon, ob mayInterruptIfRunning wahr oder falsch ist, wird true zurückgegeben.
Mit der isCancelled-Methode wird ermittelt, ob die Aufgabe erfolgreich abgebrochen wurde. Wenn die Abbruchmethode erfolgreich ist, gibt sie „true“ zurück, andernfalls gibt sie „false“ zurück.
isDone wird verwendet, um zu bestimmen, ob die Aufgabe abgeschlossen ist, und gibt true zurück, wenn die Aufgabe abgeschlossen ist. Der Aufgabenabschluss umfasst den normalen Abschluss, den Aufgabenabbruch und die Aufgabenausnahme, die alle „true“ zurückgeben.
Die Methode get() wird verwendet, um das Ausführungsergebnis zu erhalten. Diese Methode führt zu einer Blockierung und kehrt erst zurück, wenn die Aufgabenausführung abgeschlossen ist ;
get(long timeout, TimeUnit unit) wird verwendet, um das Ausführungsergebnis zu erhalten. Wenn das Ergebnis nicht innerhalb der angegebenen Zeit erhalten wird, wird eine java.util.concurrent.TimeoutException-Ausnahme ausgelöst
FutureTask implementiert die RunnableFuture-Schnittstelle und RunnableFuture erbt die Schnittstellen Future
II, Zukunft und FutureTaskNutzung und Analyse
1 Bei Verwendung von Future müssen wir die Callable-Schnittstelle implementieren und das zurückgegebene Future-Objekt über die Submit-Methode der ExecutorService-Schnittstelle abrufen
2 Laut dem Konstruktor von FutureTask können wir sehen, dass FutureTask beides hat. Sie können die Implementierungsklasse von Callable oder die Implementierungsklasse von Runnable erhalten. Wenn Sie die Implementierungsklasse von Callable übergeben, können Sie das Ergebnis der Thread-Ausführung erhalten. Wenn Sie die Implementierungsklasse von Runnable übergeben, müssen Sie eine von Ihnen angegebene Thread-Abschlusskennung übergeben, da die Implementierung von Runnable keinen Rückgabewert hat set, also result. Wenn der Thread endet, wird Ihnen der ursprüngliche Ergebniswert zurückgegeben. Der Konstruktor von FutureTask lautet wie folgt:
public class FutureTask<V> implements RunnableFuture<V>{ public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable } public FutureTask(Runnable runnable, V result) { this.callable = Executors.callable(runnable, result);//runnable转化为callable this.state = NEW; // ensure visibility of callable } }
Als nächstes schauen wir uns den Future-spezifischen Verwendungscode mit FutureTask an:
// 执行任务 实现Runnable FutureTaskJobRunnable taskRun = new FutureTaskJobRunnable(); // 执行任务 实现Callable FutureTaskJobCallable taskCall = new FutureTaskJobCallable(); String val = "ok"; // 线程运行成功后把,返回你传入的val值 FutureTask<String> futureTaskRun = new FutureTask<String>(taskRun, val); // 线程运行,返回线程执行的结果 FutureTask<String> futureTaskCall = new FutureTask<String>(taskCall); //声明线程池 ExecutorService executor = Executors.newCachedThreadPool(); //Future Future<String> future = executor.submit(taskCall); System.out.println(future.get()); //FutureTask executor.submit(futureTaskCall); System.out.println(futureTaskCall.get()); //FutureTask自定义线程执行 new Thread(futureTaskRun).start(); System.out.println(futureTaskRun.get());
public class FutureTaskJobCallable implements Callable<String>{ public String call() throws Exception { System.out.println("FutureTaskJobCallable已经执行了哦"); Thread.sleep(1000); return "返回结果"; } } public class FutureTaskJobRunnable implements Runnable { public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("FutureTaskJobRunnable已经执行了哦"); } }
Gemäß dem oben Gesagten Code senden wir die Methode über die ExecutorService-Schnittstelle. Werfen wir zunächst einen Blick auf die spezifische Implementierung der Submit-Methode in der AbstractExecutorService-Klasse.
public Future<?> submit(Runnable task) { if (task == null) throw new NullPointerException(); RunnableFuture<Void> ftask = newTaskFor(task, null); execute(ftask); return ftask; } public <T> Future<T> submit(Runnable task, T result) { if (task == null) throw new NullPointerException(); RunnableFuture<T> ftask = newTaskFor(task, result); execute(ftask); return ftask; } public <T> Future<T> submit(Callable<T> task) { if (task == null) throw new NullPointerException(); RunnableFuture<T> ftask = newTaskFor(task); execute(ftask); return ftask; } protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) { return new FutureTask<T>(runnable, value); } protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) { return new FutureTask<T>(callable); }
Sie können sehen, dass, wenn Sie die Submit-Methode zum Senden einer Aufgabe verwenden, diese über die newTaskFor-Methode in ein FutureTask-Objekt konvertiert wird. Lassen Sie uns also analysieren Die drei Punkte im obigen Code im Detail. Fälle:
1. Wenn Sie die Runaable-Klasse oder Callable-Klasse übergeben, die Sie selbst implementiert haben, hilft Ihnen die Sumbit-Methode natürlich dabei, sie automatisch in ein FutureTask-Objekt zu kapseln. und erhalten Sie das Ergebnis nach der Ausführung über das Future-Objekt.
2、你传入的已经是个自己构造的FutureTask对象,由于FutureTask其实是实现了Runnable接口的,它本身就是个Runaable实现类, sumbit方法还是会将它视为Runnable类来进行封装,并最终会执行FutureTask自己的run方法,一系列实现都在你传入的FutureTask对象内完成,所以你可以直接通过自己构建的FutureTask获取结果;
3、自己单独声明线程运行,跟第2点类似,FutureTask本身就是个Runnabel实现类,自然可以做为参数传入Thread运行;
那么我们把自定义的Runnable、Callable实现类做为参数构造FutureTask后,FuttureTask是如何运行的呢,我们可以看下FuttureTask中具体的代码实现
//你传入的Runnable与Callable实现类都会在构造函数中转化为Callable private Callable<V> callable; public void run() { if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread())) return; try { Callable<V> c = callable;//你传入的实现类 if (c != null && state == NEW) { V result;//返回值 boolean ran; try { result = c.call();//运行后返回结果 ran = true; } catch (Throwable ex) { result = null; ran = false; setException(ex); } if (ran) set(result); } } finally { // runner must be non-null until state is settled to // prevent concurrent calls to run() runner = null; // state must be re-read after nulling runner to prevent // leaked interrupts int s = state; if (s >= INTERRUPTING) handlePossibleCancellationInterrupt(s); } }
可以看到FutureTask类本身的run方法,就是执行Runnable、Callable的实现类并获取返回结果的过程。
所以ExecutorService接口中submit方法归根结底还是要把你传入的对象封装成FutureTask对象,并通过FutureTask类的内部实现来获取结果的,返回的Future接口对象也要依赖于FutureTask实例化的,所以无论是直接传入自己的Runnable、Callable实现类还是构建FutureTask传入,本质上都是通过FutureTask去实现,没有什么区别;
Das obige ist der detaillierte Inhalt vonDie Beziehung und Verwendung zwischen Future und FutureTask in Java (mit Code). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen

Leitfaden zur perfekten Zahl in Java. Hier besprechen wir die Definition, Wie prüft man die perfekte Zahl in Java?, Beispiele mit Code-Implementierung.

Leitfaden für Weka in Java. Hier besprechen wir die Einführung, die Verwendung von Weka Java, die Art der Plattform und die Vorteile anhand von Beispielen.

Leitfaden zur Smith-Zahl in Java. Hier besprechen wir die Definition: Wie überprüft man die Smith-Nummer in Java? Beispiel mit Code-Implementierung.

In diesem Artikel haben wir die am häufigsten gestellten Fragen zu Java Spring-Interviews mit ihren detaillierten Antworten zusammengestellt. Damit Sie das Interview knacken können.

Java 8 führt die Stream -API ein und bietet eine leistungsstarke und ausdrucksstarke Möglichkeit, Datensammlungen zu verarbeiten. Eine häufige Frage bei der Verwendung von Stream lautet jedoch: Wie kann man von einem Foreach -Betrieb brechen oder zurückkehren? Herkömmliche Schleifen ermöglichen eine frühzeitige Unterbrechung oder Rückkehr, aber die Stream's foreach -Methode unterstützt diese Methode nicht direkt. In diesem Artikel werden die Gründe erläutert und alternative Methoden zur Implementierung vorzeitiger Beendigung in Strahlverarbeitungssystemen erforscht. Weitere Lektüre: Java Stream API -Verbesserungen Stream foreach verstehen Die Foreach -Methode ist ein Terminalbetrieb, der einen Vorgang für jedes Element im Stream ausführt. Seine Designabsicht ist

Anleitung zum TimeStamp to Date in Java. Hier diskutieren wir auch die Einführung und wie man Zeitstempel in Java in ein Datum konvertiert, zusammen mit Beispielen.

Kapseln sind dreidimensionale geometrische Figuren, die aus einem Zylinder und einer Hemisphäre an beiden Enden bestehen. Das Volumen der Kapsel kann berechnet werden, indem das Volumen des Zylinders und das Volumen der Hemisphäre an beiden Enden hinzugefügt werden. In diesem Tutorial wird erörtert, wie das Volumen einer bestimmten Kapsel in Java mit verschiedenen Methoden berechnet wird. Kapselvolumenformel Die Formel für das Kapselvolumen lautet wie folgt: Kapselvolumen = zylindrisches Volumenvolumen Zwei Hemisphäre Volumen In, R: Der Radius der Hemisphäre. H: Die Höhe des Zylinders (ohne die Hemisphäre). Beispiel 1 eingeben Radius = 5 Einheiten Höhe = 10 Einheiten Ausgabe Volumen = 1570,8 Kubikeinheiten erklären Berechnen Sie das Volumen mithilfe der Formel: Volumen = π × R2 × H (4

PHP und Python haben jeweils ihre eigenen Vorteile, und die Wahl sollte auf Projektanforderungen beruhen. 1.PHP eignet sich für die Webentwicklung mit einfacher Syntax und hoher Ausführungseffizienz. 2. Python eignet sich für Datenwissenschaft und maschinelles Lernen mit präziser Syntax und reichhaltigen Bibliotheken.
