Javaer、あなたが理解しなければならないExecutorService

4285 ワード

ExecutorService初接触
前に行った機能には、データベース内の対応するレコードを処理し、各処理後の結果をソートする時間のかかる操作がありました.申し訳ございませんが、最初は直接単一スレッドで処理していました!信じる勇気があるのか?!そして60万件以上の記録が、3分走ってやっと結果が出た!その時私はショックを受けました.このニマは「いじめ」のリズムになりますね.しかし、私は良い解決策がなくて、ボスに相談して、それからボスは直接コードをなくしていくつかの字を添付しました.
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue());
    }
ExecutorServiceでスレッドプールを走ってExecutorServiceを使った後、私はそれを好きになりました!!!
簡単な紹介ExecutorServiceとは何ですか.それはExecutorの中の方法を実現して、jdkの中でこのように紹介します
public interface ExecutorがコミットしたRunnableタスクを実行するオブジェクト.このインタフェースは、スレッドの使用の詳細、スケジュールなど、各タスクがどのように実行されるかを含むメカニズムからタスクコミットを分離する方法を提供します...このパッケージで提供されるExecutorインプリメンテーションは、より広範なインタフェースを使用するExecutorServiceを実現します.ThreadPoolExecutorクラスは、拡張可能なスレッドプール実装を提供します.Executorsクラスは、これらのExecutorに便利な工場方法を提供します.
シーンの操作
シーンについては、最近やった機能を例に挙げます.
結果を待つ必要はない
前回の採集領英情報の最後に採集が遅い原因の一つは「単一スレッドを使用する」ことです.では、ExecutorServiceを使用してスレッドプールを作成し、採集速度を速めます(コードは貼らないで、大まかな考え方を書きます):
  • スレッドプールExecutorService executorService = Executors.newCachedThreadPool();を作成するこの方法は、上限のない数のスレッドプール
  • を作成する.
  • は、収集コード中のforループの内容を抽出して、次のコード
  • のようないくつかのパラメータを伝達することができるため、統合Threadのクラスに再構成する.
    public class CacheThreadPool {
        public static void main(String[] args) {
            ExecutorService exec = Executors.newCachedThreadPool();
            for (int i = 0; i < 15; i++)
                exec.execute(new MyThread(" "+i));
            exec.shutdown();//          ,       Executor       
        }
    }
    
    class MyThread extends Thread {
    
        private String name;
    
        public MyThread(String name) {
            this.name = name;
        }
    
        @Override
        public void run() {
            System.out.println("  "+name+"      ");
        }
    }
    

    注意しなければならないのは、forループでは、スレッドの実行結果を待つ必要はありません.なぜなら、すべての解析が成功するかどうか、データベースの挿入が成功するかどうかは気にしないからです.
    結果が必要
    これが冒頭の話です.今からコースを走りますが、forループが終わったとは保証できません.各スレッドが結果を返してくれます.つまり、スレッドが60万件のデータを処理するのを待たなければなりません.結果を手に入れてから、プログラムは続けられます.jdkにはinvokeAllを提供する方法があります
      List> invokeAll(Collection extends Callable> tasks) throws InterruptedException;
    

    与えられたタスクを実行し、すべてのタスクが完了すると、タスクのステータスと結果を保持するFutureリストに戻ります.これはいわゆる「一括実行」ですか?そこで私はdemoテストを書いて、forサイクルを10回繰り返して、毎回処理するのに1 sかかります.単一スレッド処理では10 sで、厚かましくありません(他のすべての要素を排除して、最も理想的な状態)、それからinvokeAll方法で大量に実行して、私の予測結果は1 s(馬鹿も推測しました)コードは以下の通りです.
    package com.quick.thread;
    
    import java.util.concurrent.Callable;
    
    /**
     * Created by wangxc on 2017/3/29.
     */
    public class TaskSleep implements Callable {
    
        private int num;
    
        public TaskSleep(int num){
            this.num = num;
        }
    
        @Override
        public Integer call() throws Exception {
    //        System.out.println(num + "--->" +i);
            Thread.sleep(1000);
            return  num;
        }
    }
    
    package com.quick.thread;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.*;
    
    /**
     * Created by wangxc on 2017/3/29.
     */
    public class ExecutorServiceDemo {
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            long stat = System.currentTimeMillis();
            ExecutorService executorService = Executors.newCachedThreadPool();
            List callList = new ArrayList();
            for(int i=0;i<10;i++){
                callList.add(new TaskSleep(i));
            }
            List> futures = executorService.invokeAll(callList);
            executorService.shutdown();
            int sum=0;
            for(Future item:futures){
                sum += item.get();
            }
            System.out.println("  "+sum);
            long end = System.currentTimeMillis();
            System.out.println((double)(end-stat)/1000);
        }
    }
    

    結果
      45
    1.045
    

    ええ、これが私の望む結果です.
    最後にExecutorServiceの使用方法は非常に多く、自分に合ったビジネスシーンが最も主要であり、本稿では自分のビジネスニーズに応じてExecutorServiceを使用し、参考までに~