ホームページ  >  記事  >  Java  >  Java 同時実行スレッド プールの Callable と Future の詳細なコード説明

Java 同時実行スレッド プールの Callable と Future の詳細なコード説明

黄舟
黄舟オリジナル
2017-06-18 10:11:141496ブラウズ

この記事では、主に 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() を通じてスレッド プールを閉じます。


1. submit()


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;
}

説明: submit() は newTaskFor( task) RunnableFuture オブジェクト 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() のソース コードに戻ります。

newTaskFor() が新しい ftask オブジェクトを作成した後、タスクはexecute(ftask) を通じて実行されます。このとき、ftask は Runnable オブジェクトとして実行され、最終的にその run() メソッドが呼び出されます。ftask の run() メソッドは java/util/concurrent/FutureTask.java に実装されており、ソース コードは次のとおりです。 :


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) を通じて結果を保存します。

FutureTaskのget()メソッドを呼び出した後、set(result)で保存した値が返されます。

以上がJava 同時実行スレッド プールの Callable と Future の詳細なコード説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。