この記事は、Java における Future と FutureTask の関係と使用法に関するものです (コード付き)。必要な方は参考にしていただければ幸いです。 。
Future と FutureTask は両方とも、スレッド実行の戻り結果を取得するために使用されます。以下では、この 2 つの関係と使用法についての概要と分析を説明します。
#1. Future と #FutureTask の概要:Future は java.util.concurrent パッケージの下にあり、インターフェイスです。
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; }# #Future インターフェースには 5 つのメソッドが宣言されています。各メソッドの機能を以下に紹介します。 cancel メソッドは、キャンセルが成功した場合は true を返し、キャンセルされた場合は false を返します。失敗します。パラメータ MayInterruptIfRunning は、スレッドの実行中に割り込みが許可されないことを意味する false に設定され、割り込みが許可されることを意味する true に設定されます。具体的には、以下の 3 つの状況に分けられます。 1. タスクが完了した場合、mayInterruptIfRunning が true であっても false であっても、キャンセルしたいタスクが完了しているためです。 ; 2. タスクが実行中の場合は、mayInterruptIfRunning が true か false かに関係なく true が返されます。ただ、mayInterruptIfRunning が true の場合、スレッドは中断され、false の場合、スレッドは中断されずに実行を完了します。 3. タスクが実行されていない場合は、mayInterruptIfRunning が true か false に関係なく、true を返します。 isCancelled メソッドは、タスクが正常にキャンセルされたかどうかを判断するために使用されます。cancel メソッドが成功した場合は true を返し、そうでない場合は false を返します。 isDone はタスクが完了したかどうかを判断するために使用され、タスクが完了した場合は true を返します。タスクの完了には、正常終了、タスクキャンセル、タスク例外があり、いずれも実行結果を取得するために trueget() メソッドが使用されます。このメソッドはブロックを引き起こすため、タスクの実行が完了するまで戻りません。 completed;get(long timeout, TimeUnit Unit) を使用して実行結果を取得します。指定した時間内に結果が取得できない場合は、java.util.concurrent.TimeoutException 例外がスローされます。 ##FutureTask は RunnableFuture インターフェイスを実装し、RunnableFuture は Futured94943c0b4933ad8cac500132f64757f インターフェイスを継承するため、FutureTask は Futured94943c0b4933ad8cac500132f64757f インターフェイスのすべてのメソッドを実装するだけでなく、独自の run メソッドも確認できます。クラス図
#、将来と #FutureTask
使用法と分析 1. Future を使用する場合、FutureTask のコンストラクターに従って、Callable インターフェイスを実装し、ExecutorService インターフェイスの submit メソッドを通じて返された Future オブジェクトを取得する必要があります。 FutureTask では、FutureTask が Callable の実装クラスと Runnable の実装クラスの両方を受け取ることができることがわかります。 Callable の実装クラスを渡すと、Runnable の実装クラスを渡すとスレッドの実行結果を取得できます。Runnable の実装には戻り値がないため、設定したスレッド完了識別子を渡す必要があります。これは結果です。スレッドが終了すると、渡した元の結果値が返されます。FutureTask のコンストラクターは次のとおりです。 # 次に、FutureTask の将来固有の使用法コードを見てみましょう: 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
}
}
// 执行任务 实现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());上記のコードによるとでは、ExecutorService インターフェイスからメソッドを送信します。まず、AbstractExecutorService クラスの submit メソッドの具体的な実装を見てみましょう。
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已经执行了哦"); } }submit メソッドを使用してタスクを送信すると、newTaskFor メソッドを通じて FutureTask オブジェクトに変換されることがわかります。それでは分析してみましょう上記のコードの 3 つのポイントを詳しく説明します。 状況: 1. 自分で実装した Runaable クラスまたは Callable クラスを渡す場合、sumbit メソッドはそれを FutureTask オブジェクトに自動的にカプセル化するのに役立ちます。を実行し、実行後に Future オブジェクトを通じて結果を取得します。
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去实现,没有什么区别;
以上がJavaにおけるFutureとFutureTaskの関係と使い方(コード付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。