javaスレッド池、アリはなぜExectorsを使用することができませんか?

6644 ワード

問題がある
  • アリJavaコード仕様は、なぜExectorsを使用してスレッドを素早く作成することができないのですか?
  • 以下のコード出力は何ですか?
  • ThreadPoolExecutor executor = new ThreadPoolExecutor(
            1, //corePoolSize
            100, //maximumPoolSize
            100, //keepAliveTime
            TimeUnit.SECONDS, //unit
            new LinkedBlockingDeque<>(100));//workQueue
    
    for (int i = 0; i < 5; i++) {
        final int taskIndex = i;
        executor.execute(() -> {
            System.out.println(taskIndex);
            try {
                Thread.sleep(Long.MAX_VALUE);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
    }
    A)0 1 2 3 4 5
    B)0~5の順番が一致しないで5行出力します.
    C)0
    基礎
    スレッド池とは?
    スレッドプールはプールを通してリソースセットであり、どの池の役割も大同小異であり、主にリソースの作成、初期化のためのシステムオーバーヘッドを減らすために使用されます.
    スレッドを作るのは「高い」ですか?
    はい、そうです.スレッドを作成すると高価です.
    システムの各プロセスには独自のメモリ空間があり、ライト級プロセスと呼ばれるスレッドも必要であることを知っています.
    JVMにおいてデフォルトのスレッドは256 k〜1 M(32ビットまたは64ビットのオペレーティングシステムに依存)のメモリを使用する必要がある.(具体的な配列は詳しく調べません.JVMバージョンの変化に伴い、このデフォルト値はいつでも変更される可能性があります.スレッドがメモリを使う必要があることを知っているだけです.)
    メモリ以外にもっとありますか?多くの文章はコンテキスト切り替え、CPUスケジュールを中に入れていますが、ここでスレッドスケジュールを入れないのは、睡眠中のスレッドがスケジュールされていないからです.睡眠中のスレッドでないと、スケジュールが必ず必要です.ただし、JVMでは、作成時のメモリ消費以外にもGCに圧力をかけます.スレッドを頻繁に作成する場合は、対応するスレッドを回収する必要があります.
    スレッド池のメカニズム?
    スレッドプールはスレッドを繰り返し利用する技術であり、スレッド池の主な仕組みは、スレッド数を一定に残して、何もしない時に眠らせ、アクティブにする時にはスレッドを持って実行することである.これらはスレッド池の実現に関わる具体的な戦略です.
    どのようなよくある池がありますか?
  • スレッド池
  • 接続池(データベース接続、TCP接続など)
  • BufferPool
  • Javaのスレッドの池
    UML図(Java 8)
    本当の実現類が見られます.
  • ThreadPoolExector(1.5)
  • Fork JoinPool(1.7)
  • ScheduledThreadPool Exector(1.5)
  • 今日は主にThreadPoolExecutorについて話します.これも利用率の高い実現です.
    Exectorsが提供する工場方法
  • newCachedThreadPool(ThreadPool Exector)
    キャッシュ可能なスレッドを作成します.スレッドのサイズが処理に必要なスレッドを超えていると、空き領域(60秒実行しないタスク)のスレッドが回収され、ジョブ数が増加すると、新しいスレッドがスマートに追加されてタスクが処理されます.このスレッドプールはスレッドサイズに制限がありません.スレッドサイズはオペレーティングシステム(またはJVM)が作成できる最大スレッドサイズに完全に依存します.
  • newFixedThreadPool(ThreadPool Exector)
    固定サイズのスレッドを作成します.スレッドがスレッドの最大サイズに達するまで、タスクを提出するたびにスレッドを作成します.スレッドのサイズが最大値に達するとそのまま維持されますが、あるスレッドが異常実行のために終了すると、スレッドの新しいスレッドが追加されます.
  • newSingleThreadExector(ThreadPool Exector)
    単スレッドのスレッドを作成します.このスレッド池ではスレッドが一つしかなく、つまり単一スレッドのシリアルに相当するすべてのタスクを実行します.この唯一のスレッドが異常に終了すると、新しいスレッドが代替されます.このスレッドプールは、すべてのタスクの実行順序をタスクの提出順に実行することを保証します.
  • newScheduledThreadPool(ScheduledThreadPool Exector)
    無限サイズのスレッドプールを作成します.このスレッドはタイミングと周期的にタスクを実行する必要があります.
  • newSingleThreadScheduledExector(ScheduledThreadPool Exector)
    タイミングと周期的にタスクを実行するための単一スレッドを作成します.
  • newWork StealingPool(1.8 Fork JoinPool)
    ジョブを作成して盗む
  • 様々な工場法で使われているスレッド池実現類は最終的に3つしかなく、対応関係は以下の通りです.
    工場の仕様
    実装クラス
    newCachedThreadPool
    ThreadPool Exector
    newFixedThreadPool
    ThreadPool Exector
    newSingle ThreadExector
    ThreadPool Exector
    newScheduledThreadPool
    ScheduledThreadPoolExector
    newSingleThreadScheduledExector
    ScheduledThreadPoolExector
    newWork Stealing Pool
    Fork JoinPool
    ThreadPool Exector
    まず、ThreadPoolExecutorの完全な構造関数を見ます.
    public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue workQueue,
                                  ThreadFactory threadFactory,
                                  RejectedExecutionHandler handler)
  • corePoolSize
    コアプールのサイズは、allowCoreThreadTimeOutが設定されていない限り、スレッドが空き時間を超えても、この数のスレッドは少なくともプールに保持されます.
    corePoolSizeに必要なスレッドはすぐに作成されたものではなく、タスクを提出した後に作成する必要がありますので、大量のキャッシュスレッド数があれば、まず空きタスクを提出してスレッドを最初に作成して、その後の実行効率を向上させてもいいです.
  • maximPoolSize
    許可された最大スレッド数.
  • keep Alive Time
    アイドルスレッドの空き時間は、コアスレッドがallowCoreThreadTimeOutによってtrueになります.
  • ユニットkeepAliveTimeと協力して、keepAliveTimeの単位を設定する.例えば、ミリ秒、秒.
  • work Que
    スレッドプールのタスクキュー.上述したスレッド池の主な役割は多重スレッドであり、タスクを処理するために必要なキューを保存する必要があります.これらのタスクを処理するために池のスレッドを使用するためには、タスクのキューが必要です.
  • threadFactory
    スレッド池が新しいスレッドが必要であると判断した場合は、スレッドプロジェクトを介してスレッドを作成します.
  • ハンドル
    ブロックされた時の処理プログラムを実行すると、スレッド池は処理できません.これはタスクのキューに関連しています.例えば、キューのサイズを指定できます.このサイズを超えたらどうすればいいですか?JDKはすでに私達のために考慮し、4つのデフォルト実装を提供しています.
    以下はJDKのデフォルトの携帯戦略です.
  • AbortPolicy(デフォルト)RejectedExecutionExceptionを投げると異常です.
  • CallerRunsPolicy
    現在のスレッドがあるスレッドを呼び出して実行します.
  • DisccardPolicy
    現在のタスクを直接破棄します.
  • DisccardOldest Policy
    一番古いタスクを破棄して、現在のタスクをキューに追加します.
  • 紛らわしいパラメータ:corePoolSize maximPoolSize workQue
    タスクキュー、コアスレッド数、最大スレッド数の論理関係
  • スレッド数がコアスレッド数より小さい場合、スレッドを作成します.
  • スレッド数がコアスレッド数以上であり、タスクキューがいっぱいでない場合、タスクをタスクキューに入れる.
  • スレッド数がコアスレッド数以上で、タスクキューがいっぱいです.
  • スレッド数が最大スレッド数より小さい場合、スレッド
  • を作成します.
  • スレッド数が最大スレッド数に等しい場合、実行拒否処理プログラムを起動する(デフォルトの効果は、例外をスローし、ジョブを拒否する)
  • .
    この三つのパラメータはどのように設定すればいいですか?最適値がありますか?
    JAVAは協働のサポートが不友好なので、スレッドとスレッドに大きく依存します.この値は最適な推薦がないため、業務ニーズに応じて設定する必要があります.異なるデマンド型は、複数の異なるスレッド池を作成して実行することができる.
    問題1:アリ開発規範はなぜExectorsがスレッドを素早く作成することができないのですか?
    参照先:https://github.com/alibaba/p3c
    理由が見えるのは簡単です.
  • newSingleThreadExector
  • newFixedThreadPool
  • workQueueパラメータで直接new LinkedBlockingQueue()を使用して、スレッドプールに無限にタスクを追加することができます.
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                        0L, TimeUnit.MILLISECONDS,
                                        new LinkedBlockingQueue();
    }
    
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1,
        1,
        0L,
        TimeUnit.MILLISECONDS,
        new LinkedBlockingQueue()));
    }
    スレッドプールに提出されたタスクが問題になります.例えば、sleepが恒久的であれば、メモリが漏洩し、最終的にはOOMが発生します.
    また、アリは、ユーザー定義threadFactoryにスレッド名を設定することを推奨しています.
    問題2:下記のコード出力は何ですか?
    Cを選ぶべきです最大スレッド数は100であるが、コアスレッド数は1であり、ジョブキューは100である.スレッド数がコアスレッド数以上でタスクキューがいっぱいでない場合、タスクをタスクキューに入れます.この条件ですから、今後追加されるジョブはいずれも詰まります.
    最後に
    ThreadPool Exectorについての論理は実際に使うとちょっとおかしいです.スレッド池のスレッドは最大スレッド数を超えていないので、任務が長い間滞っている時に新しいスレッドを作成して処理することができますか?
    ここではnewWork Stealing Pool、つまりFork JoinPoolをオススメします.仕事を盗むモードを取った.今後はFork JoinPoolについてみんなと話します.
    転載先:https://www.cnblogs.com/ants/p/11343657.html