ホームページ  >  記事  >  Java  >  Java が future を使用してマルチスレッドの実行結果をタイムリーに取得する方法の分析例

Java が future を使用してマルチスレッドの実行結果をタイムリーに取得する方法の分析例

黄舟
黄舟オリジナル
2017-10-12 10:20:512754ブラウズ

Java プログラミングでは、スレッドの実行結果を時間内に取得する必要がある場合があります。この記事では、Java でスレッドの実行結果を時間内に取得するために、future を使用する方法を紹介します。それを参照してください。

Future インターフェースは、java.util.concurrent パッケージ内の Java 標準 API の一部です。 Future インターフェイスは、Java スレッド Future モードの実装であり、非同期計算に使用できます。

Future を使用すると、3 段階のプログラミングを実行できます: 1. マルチスレッド タスクの開始 2. その他の処理 3. マルチスレッド タスクの結果の収集。これにより、ノンブロッキングのタスク呼び出しが実現します。途中で問題に遭遇しました。つまり、Future の結果は非同期で取得できるものの、結果があるかどうかを isdone で判定する必要があるか、get() 関数を使用して結果を取得することができます。実行結果をブロック的に返します。このように、他のスレッドの結果ステータスをリアルタイムで追跡できないため、get を直接使用する場合は注意して使用する必要があります。isdone と組み合わせて使用​​することをお勧めします。

任意のスレッドの結果をタイムリーに取得するためのより良い方法は次のとおりです。CompletionService を使用します。これは、将来の値を取得するために内部的にブロッキング キューを追加し、戻り値に基づいて対応する処理を実行します。一般的な将来の使用と CompletionService の使用の 2 つのテスト ケースは次のとおりです:


import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
 * 多线程执行,异步获取结果
 * 
 * @author i-clarechen
 *
 */
public class AsyncThread {
  public static void main(String[] args) {
    AsyncThread t = new AsyncThread();
    List<Future<String>> futureList = new ArrayList<Future<String>>();
    t.generate(3, futureList);
    t.doOtherThings();
    t.getResult(futureList);
  }
  /**
   * 生成指定数量的线程,都放入future数组
   * 
   * @param threadNum
   * @param fList
   */
  public void generate(int threadNum, List<Future<String>> fList) {
    ExecutorService service = Executors.newFixedThreadPool(threadNum);
    for (int i = 0; i < threadNum; i++) {
      Future<String> f = service.submit(getJob(i));
      fList.add(f);
    }
    service.shutdown();
  }
  /**
   * other things
   */
  public void doOtherThings() {
    try {
      for (int i = 0; i < 3; i++) {
        System.out.println("do thing no:" + i);
        Thread.sleep(1000 * (new Random().nextInt(10)));
      }
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
  /**
   * 从future中获取线程结果,打印结果
   * 
   * @param fList
   */
  public void getResult(List<Future<String>> fList) {
    ExecutorService service = Executors.newSingleThreadExecutor();
    service.execute(getCollectJob(fList));
    service.shutdown();
  }
  /**
   * 生成指定序号的线程对象
   * 
   * @param i
   * @return
   */
  public Callable<String> getJob(final int i) {
    final int time = new Random().nextInt(10);
    return new Callable<String>() {
      @Override
      public String call() throws Exception {
        Thread.sleep(1000 * time);
        return "thread-" + i;
      }
    };
  }
  /**
   * 生成结果收集线程对象
   * 
   * @param fList
   * @return
   */
  public Runnable getCollectJob(final List<Future<String>> fList) {
    return new Runnable() {
      public void run() {
        for (Future<String> future : fList) {
          try {
            while (true) {
              if (future.isDone() && !future.isCancelled()) {
                System.out.println("Future:" + future
                    + ",Result:" + future.get());
                break;
              } else {
                Thread.sleep(1000);
              }
            }
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      }
    };
  }
}

実行結果は、future がリストに追加されたときと同じ順序 (0、1、2) で出力されます。


do thing no:0
do thing no:1
do thing no:2
Future:java.util.concurrent.FutureTask@68e1ca74,Result:thread-0
Future:java.util.concurrent.FutureTask@3fb2bb77,Result:thread-1
Future:java.util.concurrent.FutureTask@6f31a24c,Result:thread-2

以下は最初です 実行を完了したスレッドが最初に処理される解決策:



import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingDeque;
public class testCallable {
  public static void main(String[] args) {
    try {
      completionServiceCount();
    } catch (InterruptedException e) {
      e.printStackTrace();
    } catch (ExecutionException e) {
      e.printStackTrace();
    }
  }
  /**
   * 使用completionService收集callable结果
   * @throws ExecutionException 
   * @throws InterruptedException 
   */
  public static void completionServiceCount() throws InterruptedException, ExecutionException {
    ExecutorService executorService = Executors.newCachedThreadPool();
    CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(
        executorService);
    int threadNum = 5;
    for (int i = 0; i < threadNum; i++) {
      completionService.submit(getTask(i));
    }
    int sum = 0;
    int temp = 0;
    for(int i=0;i<threadNum;i++){
      temp = completionService.take().get();
      sum += temp;
      System.out.print(temp + "\t");
    }
    System.out.println("CompletionService all is : " + sum);
    executorService.shutdown();
  }
  public static Callable<Integer> getTask(final int no) {
    final Random rand = new Random();
    Callable<Integer> task = new Callable<Integer>() {
      @Override
      public Integer call() throws Exception {
        int time = rand.nextInt(100)*100;
        System.out.println("thead:"+no+" time is:"+time);
        Thread.sleep(time);
        return no;
      }
    };
    return task;
  }
}

最初に終了したスレッドの結果が最初に処理されます:



thead:0 time is:4200
thead:1 time is:6900
thead:2 time is:2900
thead:3 time is:9000
thead:4 time is:7100
  0  1  4  3  CompletionService all is : 10

概要

以上がJava が future を使用してマルチスレッドの実行結果をタイムリーに取得する方法の分析例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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