スレッドプールの執行

スレッドプールの執行+インタビューの質問

作成スレッド・プールは、次の2つの方法に分けられます。ThreadPoolExecutorとエグゼキュータ、使用のThreadPoolExecutorの研究に、このセクションでは、ビューのエグゼキュータは、スレッドプールを作成する方法である焦点を当てています。
執行は、以下の6つのスレッドプールを作成することができます。

  • FixedThreadPool(N):キュー内のタスクを待っているアイドルスレッドを超えて固定スレッドプールの数を作成するために、並列プログラムの最大数を制御するために使用することができます。
  • CachedThreadPool():作業スレッドプールの多くはスレッドを対応するタスクの数に応じて生成されます短い時間、及び再利用のためにキャッシュにスレッド試みは、使用されていない制限60秒の場合、それは削除キャッシュになります。
  • SingleThreadExecutor():シングルスレッドのスレッドプールを作成します。
  • ScheduledThreadPool(N):実行タイミングや定期的なタスクをサポートする、固定されたスレッドプールの数を作成します。
  • SingleThreadScheduledExecutor():このスレッドプールは、シングルスレッドnewScheduledThreadPoolです。
  • WorkStealingPool(N)、実行順序は、スレッドプールを作成するJava 8新しい方法、任意のパラメータが設定されていない場合、プロセッサの数が、スレッドの数として、現在のマシンを配置し作成するとき、スレッドプールは処理タスクを並行します保証することができません。

以下は、スレッドプールの6種類を使用して、より具体的なコードが実行されています。

FixedThreadPool使用

スレッドプールの固定数を作成し、具体的には次の通りであります:

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);
for (int i = 0; i < 3; i++) {
    fixedThreadPool.execute(() -> {
        System.out.println("CurrentTime - " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
}

次のように上記のプログラムの実行結果は以下のとおりです。

CurrentTimeを - 2019年6月27日夜08時58分58秒

CurrentTimeを - 2019年6月27日夜08時58分58秒

CurrentTimeを - 2019年6月27日夜08時58分59秒

結果を見ることができるによると、newFixedThreadPool(2)は実際には2つのスレッドを作成し、ラウンド(2回)行った後、第三の実施前に、アイドル・スレッドと、第二のために停止しました。

CachedThreadPoolの使用

次のように自動的に、特定のコードをスレッドプールを作成する機能をキャッシュでの実際のニーズによると:

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
    cachedThreadPool.execute(() -> {
        System.out.println("CurrentTime - " +
                           LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
}

次のように上記のプログラムの実行結果は以下のとおりです。

CurrentTimeを - 2019年6月27日午後9時24分46秒

CurrentTimeを - 2019年6月27日午後9時24分46秒

CurrentTimeを - 2019年6月27日午後9時24分46秒

CurrentTimeを - 2019年6月27日午後9時24分46秒

CurrentTimeを - 2019年6月27日午後9時24分46秒

CurrentTimeを - 2019年6月27日午後9時24分46秒

CurrentTimeを - 2019年6月27日午後9時24分46秒

CurrentTimeを - 2019年6月27日午後9時24分46秒

CurrentTimeを - 2019年6月27日午後9時24分46秒

CurrentTimeを - 2019年6月27日午後9時24分46秒

結果を見ることができるによると、newCachedThreadPoolは、対応するタスクを処理するために、短時間で複数のスレッドを作成し、再利用のためにそれらをキャッシュしてみてください。

SingleThreadExecutor使用

次のようにスレッドプール、特定のコードの単一のスレッドを作成します。

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 3; i++) {
    singleThreadExecutor.execute(() -> {
        System.out.println("CurrentTime - " +
                           LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
}

次のように上記のプログラムの実行結果は以下のとおりです。

CurrentTimeを - 2019年6月27日夜9時43分34秒

CurrentTimeを - 2019年6月27日夜九時43分35秒

CurrentTimeを - 2019年6月27日夜9時43分36秒

ScheduledThreadPool使用

次のように定期的なタスクは、スレッドプール、特定のコードを実行することができます作成​​します。

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(2);
scheduledThreadPool.schedule(() -> {
    System.out.println("ThreadPool:" + LocalDateTime.now());
}, 1L, TimeUnit.SECONDS);
System.out.println("CurrentTime:" + LocalDateTime.now());

次のように上記のプログラムの実行結果は以下のとおりです。

CurrentTimeを:2019-06-27T21:54:21.881

ThreadPoolの:2019-06-27T21:54:22.845

結果によると、我々は効果へのタスクの実行を設定して1秒後に見ることができます。

SingleThreadScheduledExecutor使用

次のようにシングルスレッドプール、特定のコードを実行することができる定期的なタスクを作成します。

ScheduledExecutorService singleThreadScheduledExecutor = Executors.newSingleThreadScheduledExecutor();
singleThreadScheduledExecutor.schedule(() -> {
    System.out.println("ThreadPool:" + LocalDateTime.now());
}, 1L, TimeUnit.SECONDS);
System.out.println("CurrentTime:" + LocalDateTime.now());

WorkStealingPool使用

PCのCPUプロセッサの現在の数に基づいて、新しいスレッドプール様式を作成するためのJava 8は、次のコードを使用して、スレッドプールの対応する番号を生成します。

ExecutorService workStealingPool = Executors.newWorkStealingPool();
for (int i = 0; i < 5; i++) {
    int finalNumber = i;
    workStealingPool.execute(() -> {
        System.out.println("I:" + finalNumber);
    });
}
Thread.sleep(5000);

次のように上記のプログラムの実行結果は以下のとおりです。

I:0

I:3

I:2

I:1

I:4

実行結果はnewWorkStealingPool並列処理タスク、見ることができ、及び実行順序を保証することはできません。

ThreadPoolExecutor VSエグゼキューター

ThreadPoolExecutorとエグゼキュータは、ThreadPoolExecutorは、比較的伝統的な方法のスレッドプールを作成するスレッドプールを作成するために使用されているが、エグゼキュータは、より多くのスレッドプールの種類(6種類)を提供していますが、残念ながらニュースは、実際の開発では推奨されませんエグゼキューターの方法を使用してスレッドプールを作成します。

次のように、スレッドプールを作成するための規定と同じ方法で、偶然にも「アリ・ババのJava開発マニュアル」:

エグゼキュータ・スレッド・プールを作成することができますが、ThreadPoolExecutorの方法により、このアプローチは、資源の枯渇の危険性を回避するために、読者が動作ルールに明確なスレッドプールを作成することができますされていません。

説明:次のようにエグゼキュータ医療過誤スレッドプールは、返されたオブジェクト:

1)FixedThreadPool和SingleThreadPool:

Integer.MAX_VALUEの許可要求キューの長さは、それによってOOMを引き起こす、多数の要求を蓄積してもよいです。

2)CachedThreadPool和ScheduledThreadPool:

スレッドの数がOOMを得、多数のスレッドを作成することは、Integer.MAX_VALUEを可能にするために作成しました。

OOMは略称でOutOfMemoryErrorが、メモリオーバーフローの意味を参照します。

なぜエグゼキュータの使用を許可していませんか?

簡単な例で見てみましょう:

ExecutorService maxFixedThreadPool =  Executors.newFixedThreadPool(10);
for (int i = 0; i < Integer.MAX_VALUE; i++) {
    maxFixedThreadPool.execute(()->{
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
}

JVM(Java仮想マシン)起動パラメータを設定した後:-Xmx10m -Xms10mプログラムを実行するために(JVMは、最大動作メモリ10Mに等しくなるように設定)、次のようにOOM例外情報がスローされます。

スレッドの例外「メイン」java.lang.OutOfMemoryErrorを:GCオーバーヘッドの制限超過

java.util.concurrent.LinkedBlockingQueue.offerで(LinkedBlockingQueue.java:416)

java.util.concurrent.ThreadPoolExecutor.executeで(ThreadPoolExecutor.java:1371)

xxx.mainで(xxx.java:127)

なぜでしょう欠陥OOMのエグゼキュータ?

上記のコードでは、我々は次のようにFixedThreadPoolのソースコードがあるが見つかりました:

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
}

あなたはLinkedBlockingQueueは、LinkedBlockingQueueは、問題の根本を見つけるソースコードを表示し続けるFixedThreadPoolは、タスクキューとして使用作成見ることができ、ソースコードは、以下のようにされています。

public LinkedBlockingQueue() {
    this(Integer.MAX_VALUE);
}

それにタスクが大きすぎるので、複数のタスクを超える追加するキュースレッドプールにプログラムを引き起こす指定された長さは、Integer.MAX_VALUEのデフォルトの長さを、与えていないLinkedBlockingQueueを使用した場合、OOMのリスクがあります。

関連インタビューの質問

1.次のプログラムが出力されますどのような結果?

public static void main(String[] args) {
    ExecutorService workStealingPool = Executors.newWorkStealingPool();
    for (int i = 0; i < 5; i++) {
        int finalNumber = i;
        workStealingPool.execute(() -> {
            System.out.print(finalNumber);
        });
    }
}

A:いいえ、任意の出力B:出力0-4 Dの乱数(0,4含む):上記のためのすべてを出力0-4(0,4を含む)は、デジタルCを注文

回答:C

トピック解決:newWorkStealingPool内部実装は、異なるスレッドが同時に実行処理するために、次に割り当てタスクを再帰的に分割統治アルゴリズムを使用してより小さなサブタスクにタスクを分割し、そしてすることによって動作し、ForkJoinPoolあります。

2.Executorsシングルスレッドのスレッド・プールを作成することができますか?どのように作成するには?

A:エグゼキュータは、シングルスレッドのスレッドプールを作成することができ、二つの方法に分け作成します:

  • Executors.newSingleThreadExecutor():シングルスレッドのスレッドプールを作成します。
  • Executors.newSingleThreadScheduledExecutor():シングルスレッドプールを実行することができ、定期的タスクを作成します。

3.Executorsは短時間のスレッドで多数のタスクを実行するには?

A:newCachedThreadPool()短期多数のタスクを処理するのに適し。それは短時間で多数のタスクを処理するために、より適しているので、それは何のキャッシュタスクが新しいタスクを作成しません場合は、キャッシュと再利用をスレッドしようと、以上60秒スレッドの制限時間あれば、スレッドプールは、削除されます。

4.あなたは、スレッドプールを持って定期的なタスクを実行することができますか?

A:周期タスクスレッドプールは、2つを持って行う、すなわち:newScheduledThreadPool()およびnewSingleThreadScheduledExecutor()、newSingleThreadScheduledExecutor()はnewScheduledThreadPool()シングルスレッドバージョンです。

8新しいスレッド・プールとは何5.JDK?特徴は何ですか?

:JDK 8新しいスレッドプールはnewWorkStealingPool(n)は、同時の数が指定されていない場合、(すなわち、N指定されていない)、newWorkStealingPool()であるCPUプロセッサの現在の数に基づいて、スレッドプールの対応する数を生成します。これは、並列処理タスクの実行順序を特徴とする、タスクが保証されません。

6.newFixedThreadPoolとThreadPoolExecutorの関係は何ですか?

A:newFixedThreadPoolはnewFixedThreadPoolの底部はThreadPoolExecutorによって達成され、ThreadPoolExecutorパッケージです。

次のようにソースを実現newFixedThreadPool:

public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>(),
                                  threadFactory);
}

7.シングルスレッドのスレッドプールがあるの存在の意味は何ですか?

A:シングルスレッドのスレッドプールがキューイングを提供し、複数のタスクの実行キューがある場合は、タスクの順序を行って保証することができます。シングルスレッドのスレッドプールは、スレッドを作成し、破壊のシステムパフォーマンス・オーバーヘッドを低減する、既存のスレッドを再利用することができます。

8.なぜむしろエグゼキューよりも、作成ThreadPoolExecutorスレッドプールを使用することをお勧めしますか?

A:使用ThreadPoolExecutorは、資源の枯渇の危険性を回避するために、より明示的な運用ルールのスレッドプールに開発を可能にします。

次のように執行は、スレッドプールの不利益に戻ります。

  • Integer.MAX_VALUEののFixedThreadPoolとSingleThreadPool許可要求キューの長さは、メモリオーバーフローを引き起こす可能性が多数の要求を蓄積することがあります。
  • スレッドのCachedThreadPoolとScheduledThreadPool数は、メモリのオーバーフローを引き起こす可能性があり、多数のスレッドを作成するためには、Integer.MAX_VALUEの作成を可能にします。

概要

エグゼキュータは短時間で)実行単位時間、newCachedThreadPool(内のタスクの固定数の処理タスクの数が多い、newSingleThreadExecutorを(newFixedThreadPool()スレッドプールの6種類を作成する)とnewSingleThreadScheduledExecutor()シングルスレッドのスレッドプールであることができ、そしてnewSingleThreadScheduledExecutor()定期的なタスクを実行することができるnewWorkStealingPool()は、スレッドプール番号比較を処理する現在の世代のコンピュータのCPUの数に応じて、新しいJDK 8並行スレッドプールであるが、シングルスレッド・バージョンnewScheduledThreadPool(N)であるが、その実装は、タスクの実行を保証するものではありません同時実行順序です。


私は公共の数の関心を歓迎し、「返信キーワードのJavaを両手贈り物があるだろう、」!私はあなたに成功したインタビューをしたいです

%97%E5%8F%B7 %E4%BA%8C%E7%BB%B4%E7%A0%81.png)

おすすめ

転載: www.cnblogs.com/dailyprogrammer/p/12272748.html