目次
2. CountDownLatch.await()を使用します
3、UseExecutorService.awaitTermination()
序文
日常の開発では、同期的に実行する必要があるスレッドに必ず遭遇します。つまり、メインスレッドは子スレッドの実行を待って次の操作を完了する必要があり、スレッドは特定の時間内に実行する必要があります。スクリプトの実行など、ExecutorServiceスレッドプールを使用してニーズを完了することができます。おおよそ3つの方法があることを理解しています。
1. Future.get()を使用します
簡単に言うと、Futureは、タスクのキャンセル、タスククエリ、および特定の実行可能タスクと呼び出し可能タスクの実行結果の結果の取得を実行するものです。名前から派生する必要があります。結果への接続である必要があります。オブジェクトが取得、その時間上記のタスクは完了していません。これが、Futureと呼ばれる理由の1つです。したがって、Future.get()メソッドを呼び出して結果を強制的に取得すると同時に、タイムアウト期間を設定する必要があります。タイムアウトが期限切れになると、手動でタスクをキャンセルします。コード例は次のとおりです。
@Test
public void test09() {
ExecutorService executorService = Executors.newFixedThreadPool(10);
// 采用Future
Future<Boolean> future = executorService.submit(() -> {
Thread.sleep(3000);
System.out.println("线程执行完成");
return true;
});
try {
if (future.get(4, TimeUnit.SECONDS)) {
System.out.println("任务执行成功");
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
System.out.println("执行超时");
future.cancel(true);
}
}
2. CountDownLatch.await()を使用します
同期補助クラスは、操作を実行しているスレッドのセットが完了するまで1つ以上のスレッドが待機できるように設計されています。つまり、同期待機です。このメソッドは、上記の要件を完了するときに、スレッドの数を事前に知る必要があります。 、それ自体が類似しているため、カウンターの場合、最初に指定された数のスレッドを初期化する必要があります。1つが完了するたびに、カウンターはデクリメントされます。カウンターの値が0より大きい限り、メインスレッドがブロックされました。このタイプのawaitblocking waitを呼び出すときは、タイムアウトを設定するのが最善であることに注意してください。そうしないと、デッドロックが発生しやすくなります。簡単なコード実装を見てみましょう。
@Test
public void test09() {
ExecutorService executorService = Executors.newFixedThreadPool(100);
CountDownLatch countDownLatch = new CountDownLatch(1);
executorService.execute(() -> {
try {
Thread.sleep(3000);
System.out.println("线程执行完成");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
countDownLatch.countDown();
}
});
try {
if (countDownLatch.await(4, TimeUnit.SECONDS)) {
System.out.println("任务执行成功");
} else {
System.out.println("执行超时");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
3、UseExecutorService.awaitTermination()
このメソッドは、常にすべてのタスクの終了またはタイムアウト期間がすぐに終了するのを待ちます。すべてのタスクが正常に実行された場合はtrueを返し、そうでない場合はfalseを返します。現在のスレッドプールを閉じる必要があることに注意してください。または最後に手動でキャンセルします。タスク、スレッドプールを閉じる必要があるため、イベントを処理する1回限りのタスクでない限り、現在のスレッドプールを再利用する必要がある場合は、スレッドプールが作成され、毎回繰り返し実行されます。実行される時間。これは最善の選択ではありません。単純な実装を見てください。
@Test
public void test09() {
ExecutorService executorService = Executors.newFixedThreadPool(100);
executorService.execute(() -> {
try {
Thread.sleep(3000);
System.out.println("线程执行完成");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
try {
if (executorService.awaitTermination(2, TimeUnit.SECONDS)) {
System.out.println("主线程开始执行");
} else {
System.out.println("执行超时");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
executorService.shutdown();
}
}