目次
スレッドプールはソースコード内のスレッドをどのように再利用しますか?
Javaスレッドプールを知っていますか?スレッドプールを使用しましたか?まず、スレッドプールのコアパラメータについて説明しましょう。。。申し訳ありませんが、戻って見ていきます。
尊厳のために、今日のインタビュー中にスレッドプールでいくつかのインタビューの質問を整理しましょう!
なぜスレッドプールを使用するのですか?
- スレッドの再利用。スレッドの再利用はスレッドプール設計の焦点です。プログラムを実行するために1000スレッドを開く必要がある場合、システムは1000スレッドを作成します。スレッドプールを使用して1000タスクを実行する場合、開く必要はありません。 1000スレッドの場合、corePoolSizeコアを設定するだけで済みます。スレッド数、スレッドの最大数、およびキューのサイズは、スレッド置換タスクに再利用でき、1000スレッドの切り替え効率は低くありません。つまり、スレッドは必ずしも効率的ではありません。したがって、マルチスレッド環境の実際の開発では、マルチスレッドを使用することをお勧めします。
- スレッドをより適切に管理します。ThreadPoolExecutorは、スレッドの数を制御し、実際のアプリケーションシナリオに従ってキューの数と飽和戦略を設定できます。
スレッドプールのコアパラメータについてどう思いますか?
- corePoolSize:コアスレッドサイズ。スレッドプールは常に実行されており、コアスレッドは停止しません。
- maximumPoolSize:スレッドプール内のスレッドの最大数。非コアスレッドの数= maximumPoolSize-corePoolSize
- keepAliveTime:非コアスレッドのハートビート時間。非コアスレッドがkeepAliveTime内でタスクを実行しない場合、非コアスレッドは停止します。
- workQueue:キューをブロックしています。ArrayBlockingQueue、LinkedBlockingQueueなどは、スレッドタスクを格納するために使用されます。
- defaultHandler:飽和戦略。
- ThreadFactory:スレッドファクトリ。新しいスレッドファクトリを作成します。
実行タスクを追加する方法は?
- スレッドプールはexecute / submitメソッドを実行して、タスクをスレッドプールに追加します。タスクがコアスレッドの数corePoolSizeより小さい場合、スレッドプールに新しいスレッドを作成できます。
- タスクがコアスレッドの数corePoolSizeより大きい場合、タスクはブロッキングキューに追加されます。
- ブロッキングキューがいっぱいの場合は、パラメータ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のタスクが実行されました。他のいくつかの戦略を参照して実装できます。
通常、スレッドプールをどのように使用しますか?
- 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]と呼ばれています。