この記事では、主に Java 同時実行スレッド プールの Callable と Future について詳しく紹介します。興味のある方は、
Callable と Future の紹介
Callable と Future の方が興味深い組み合わせです。スレッドの実行結果を取得する必要がある場合に使用する必要があります。 Callable は結果を生成するために使用され、Future は結果を取得するために使用されます。
1. Callable
Callable は、call() メソッドのみを含むインターフェイスです。 Callable は結果を返すタスクであり、例外をスローする可能性があります。
理解を容易にするために、Callable を Runnable インターフェイスと比較することができます。Callable の call() メソッドは Runnable の run() メソッドに似ています。
Callable のソース コードは次のとおりです:
public interface Callable<V> { V call() throws Exception; }
説明: これから、Callable がジェネリックスをサポートしていることがわかります。
2. 未来
未来はインターフェースです。非同期計算の結果を表すために使用されます。計算が完了したかどうかを確認するメソッド、計算の完了を待つメソッド、および計算結果を取得するメソッドが提供されます。
Future のソースコードは次のとおりです。
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; }
説明: Future は、非同期計算の結果を表すために使用されます。その実装クラスは FutureTask です。FutureTask を説明する前に、まず Callable、Future、FutureTask の関係図を次のように見てみましょう。 Runnable と Future の 2 つのインターフェイスを継承します。 RunnableFuture のソース コードは次のとおりです。
public interface RunnableFuture<V> extends Runnable, Future<V> { void run(); }(02) FutureTask は RunnableFuture インターフェイスを実装します。したがって、Future インターフェイスを実装しているとも言えます。 サンプルとソースコード分析(JDK1.7.0_40ベース)
まずサンプルを通してCallableとFutureの基本的な使い方を見て、次にサンプルの実装原理を分析しましょう。
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(); } }
実行結果:
4950
メインスレッド main で、newSingleThreadExecutor() を通じて新しいスレッド プールを作成します。次に、Callable オブジェクト c1 を作成し、pool.submit(c1) による処理のために c1 をスレッド プールに送信し、返された結果を Future オブジェクト f1 に保存します。次に、f1.get() を通じて Callable に保存された結果を取得し、最後に pool.shutdown() を通じてスレッド プールを閉じます。
submit() は java/util/concurrent/AbstractExecutorService.java に実装されています。そのソースコードは次のとおりです:
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; }
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) { return new FutureTask<T>(callable); }
2. FutureTask の
constructor
FutureTask のコンストラクターは次のとおりです:
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. run() メソッド
やってみようsubmit() のソース コードに戻ります。
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); } }
説明:
run() は、Callable オブジェクトの call() メソッドを実行し、最後に結果を result に保存し、set(result) を通じて結果を保存します。
以上がJava 同時実行スレッド プールの Callable と Future の詳細なコード説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。