スレッドプールインタビューに必要

目次

なぜスレッドプールを使用するのですか?

スレッドプールのコアパラメータについてどう思いますか?

実行タスクを追加する方法は?

飽和戦略を知っていますか?

通常、スレッドプールをどのように使用しますか?

スレッドプールはソースコード内のスレッドをどのように再利用しますか?

総括する


Javaスレッドプールを知っていますか?スレッドプールを使用しましたか?まず、スレッドプールのコアパラメータについて説明しましょう。申し訳ありませんが、戻って見ていきます。

image.png

尊厳のために、今日のインタビュー中にスレッドプールでいくつかのインタビューの質問を整理しましょう!

 

なぜスレッドプールを使用するのですか?


  1. スレッドの再利用スレッドの再利用はスレッドプール設計の焦点です。プログラムを実行するために1000スレッドを開く必要がある場合、システムは1000スレッドを作成します。スレッドプールを使用して1000タスクを実行する場合、開く必要はありません。 1000スレッドの場合、corePoolSizeコアを設定するだけで済みます。スレッド数、スレッドの最大数、およびキューのサイズは、スレッド置換タスクに再利用でき、1000スレッドの切り替え効率は低くありません。つまり、スレッドは必ずしも効率的ではありません。したがって、マルチスレッド環境の実際の開発では、マルチスレッドを使用することをお勧めします。
  2. スレッドをより適切に管理します。ThreadPoolExecutorは、スレッドの数を制御し、実際のアプリケーションシナリオに従ってキューの数と飽和戦略を設定できます。

 

スレッドプールのコアパラメータについてどう思いますか?


  • corePoolSize:コアスレッドサイズ。スレッドプールは常に実行されており、コアスレッドは停止しません。
  • maximumPoolSize:スレッドプール内のスレッドの最大数。非コアスレッドの数= maximumPoolSize-corePoolSize
  • keepAliveTime:非コアスレッドのハートビート時間。非コアスレッドがkeepAliveTime内でタスクを実行しない場合、非コアスレッドは停止します。
  • workQueue:キューをブロックしています。ArrayBlockingQueue、LinkedBlockingQueueなどは、スレッドタスクを格納するために使用されます。
  • defaultHandler:飽和戦略。
  • ThreadFactory:スレッドファクトリ。新しいスレッドファクトリを作成します。

 

実行タスクを追加する方法は?


image.png

  1. スレッドプールはexecute / submitメソッドを実行して、タスクをスレッドプールに追加します。タスクがコアスレッドの数corePoolSizeより小さい場合、スレッドプールに新しいスレッドを作成できます。
  2. タスクがコアスレッドの数corePoolSizeより大きい場合、タスクはブロッキングキューに追加されます。
  3. ブロッキングキューがいっぱいの場合は、パラメータmaximumPoolSizeを比較して、スレッドプールに新しいスレッドを作成する必要があります。スレッド数がmaximumPoolSizeを超えると、現在設定されているスレッドプール内のスレッドを作成できなくなります。処理され、飽和戦略が実行されます。

 

 

飽和戦略を知っていますか?


上の図では、スレッド数がmaximumPoolSizeを超えると、飽和戦略が実行されると述べました。ThreadPoolExecutorクラスには4つの飽和戦略があります。RejectedExecutionHandlerインターフェースを実装する

  • AbortPolicy:スレッドタスクはエラーを破棄します。デフォルトの飽和戦略。
  • DiscardPolicy:スレッドタスクはエラーなしで直接破棄されます。
  • DiscardOldestPolicy:workQueueチームの最初のタスクを破棄し、実行のために最新のスレッドタスクをキューに再度追加します。
  • CallerRunsPolicy:スレッドプール外のスレッドは、実行のためにrunメソッドを直接呼び出します。

 

以下のコードで飽和戦略の使用法を見てみましょう。

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author :jiaolian
 * @date :Created in 2021-02-20 16:28
 * @description:线程池丢弃策略
 * @modified By:
 * 公众号:叫练
 */
public class AbortTest {

    //线程数量
    private static final int THREAD_COUNT = 50;

    private static final CountDownLatch COUNT_DOWN_LATCH = new CountDownLatch(THREAD_COUNT);

    private static final AtomicInteger ATOMIC_INTEGER = new AtomicInteger(1);

    //线程池丢弃策略
    public static void main(String[] args) throws InterruptedException {

        //新建一个线程池
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                3,5,1, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(20),new ThreadPoolExecutor.AbortPolicy());

        //DiscardPolicy 丢弃
        //AbortPolicy 丢弃报错
        //DiscardOldestPolicy 将队列对首的任务丢弃,执行当前线程任务
        //CallerRunsPolicy 直接调用run方法

        //提交线程
        for (int i=0; i<THREAD_COUNT; i++) {
            threadPoolExecutor.execute(()->{
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+" execute!"+ATOMIC_INTEGER.getAndIncrement());
                COUNT_DOWN_LATCH.countDown();
            });
        }

        COUNT_DOWN_LATCH.await();
        //关闭线程
        threadPoolExecutor.shutdown();


    }
}

上記のコード:コアスレッドの数は3、最大スレッド数は5、ブロッキングキューは20、合計50スレッドが送信されます。ここでは、飽和戦略はAbortPolicyを使用してスレッドプールの実行を分析します。プロセス。スレッドプールは最初に3つのコアスレッドワーカーを開始します。3つのスレッドが50のスレッドタスクを処理できないことがわかったため、スレッドプールがブロックキューにタスクを追加し、ブロッキングキューが50のタスクに対応できないことがわかったため、増加しました。スレッドタスクを同時に実行するために2つのスレッドに、合計5つのスレッドが同時にタスクを実行します。この時点で、実行されるスレッドプールには25のタスクがあり、25のタスクは破棄されます。 AbortPolicy飽和戦略を使用している場合、エラーが報告されます。図のカット部分は、下の赤い線で示されています。合計25のタスクが実行されました。他のいくつかの戦略を参照して実装できます。

image.png

 

通常、スレッドプールをどのように使用しますか?


  • Excutors.newSingleThreadExecutor:1 corePoolSize、LinkedBlockingQueueキューは無限に大きいです。無数のスレッドが作成されると、キューは無限に長くなり、OOMメモリオーバーフローが発生する可能性があります。シングルスレッド。
  • Executors.newCachedThreadPool:0 corePoolSize、Interger MAX_VALUEスレッドの最大数は、あなたがスレッドの無限の数を作成する際に、メモリオーバーフローがOOMを発生することがあります。小型およびマルチスレッドに適しています。
  • Executors.newFixedThreadPool:n corePoolSize、n最大スレッド数、 LinkedBlockingQueueがキューをブロックし、無数のスレッドを作成すると、キューが無限に長くなり、OOMメモリオーバーフローが発生する可能性があります。固定スレッドに適用されます。
  • Executors.newScheduledThreadPool:n corePoolSize、Interger。MAX_VALUEスレッドの最大数無数のスレッドを作成すると、OOMメモリオーバーフローが発生する可能性があります。

 

スレッドプールはソースコード内のスレッドをどのように再利用しますか?


ソースコードのThreadPoolExecutorには組み込みオブジェクトWorkerがあります。各ワーカーはスレッドです。ワーカースレッドの数はパラメーターに関連しています。各ワーカーはwhileループブロッキングキューからデータを取得し、そのrunメソッドを実行します。ワーカー内のRunnableオブジェクトを置き換えることにより、スレッド置換の効果を発揮します。そうすることの利点は、複数のスレッドの頻繁なスレッド切り替えを回避し、プログラムの実行パフォーマンスを向上させることです。

 

総括する


本日、スレッドプールでのインタビューでいくつかの重要なインタビューポイントを紹介しました。それを整理し、皆様のお役に立てれば幸いです。執筆は完了していません。同時に、修正が必要な領域がたくさんあります。I訂正してコメントしていただければ幸いです。気に入ったら、いいねしてフォローしてください。注意してください。迷子にならないでください。私はLian [公式アカウント]と呼ばれ、WeChatアカウントで[jiaolian123abc]と呼ばれています。

おすすめ

転載: blog.csdn.net/duyabc/article/details/113974598