最近のインタビューで、Java スレッドの 3 つの同期ツール クラスに関する質問に遭遇しました。マルチスレッドを学習していたときに、同期ツール クラスを注意深く勉強しませんでした。そして今ではそれさえ忘れてしまった。そこで改めて見直してみたらなかなか奥深い内容だったので、参考までに整理して記事にしました。 apache php mysql
Java は、 3 つの同期ツール クラスを提供します:
。
スレッド間の通信問題をより適切に制御するためのものです
~
1.1 CountDownLatch の概要
1 つ以上の同期を可能にする同期支援ツール実際によく使用される API は 2 つあります:
- 簡単に言うと、CountDownLatch は同期ヘルパー クラスであり、
1 つ以上のスレッドを待機させることができます。他のスレッド
がその操作を完了するまで
await()
と countDown()
使用説明:
count は CountDownLatch を初期化し、次に必要なスレッドを初期化します。 wait は await メソッドを呼び出します。 await メソッドは count=0 になるまでブロックします。他のスレッドは操作を完了した後、countDown()
を呼び出してカウンターを 1 つデクリメントします。 カウントが 0 になると、待機中のスレッドはすべて解放されますawait()
和countDown()
使用说明:
count初始化CountDownLatch,然后需要等待的线程调用await方法。await方法会一直受阻塞直到count=0。而其它线程完成自己的操作后,调用countDown()
(他のスレッドのタスク)、待機は count 変数によって制御されます。完了しました)))、実行を続行できます。
1.2 CountDownLatch の例import java.util.concurrent.CountDownLatch; public class Test { public static void main(String[] args) { final CountDownLatch countDownLatch = new CountDownLatch(5); System.out.println("现在6点下班了....."); // 3y线程启动 new Thread(new Runnable() { @Override public void run() { try { // 这里调用的是await()不是wait() countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("...其他的5个员工走光了,3y终于可以走了"); } }).start(); // 其他员工线程启动 for (int i = 0; i < 5; i++) { new Thread(new Runnable() { @Override public void run() { System.out.println("员工xxxx下班了"); countDownLatch.countDown(); } }).start(); } } }
別の例: 3 歳は現在ウェアハウス モジュール機能を担当していますが、彼の能力が低すぎて書き込みが非常に遅いです。 他の従業員は 3 歳が書き込みを完了するまで待つ必要があります。書き続けます。
import java.util.concurrent.CountDownLatch; public class Test { public static void main(String[] args) { final CountDownLatch countDownLatch = new CountDownLatch(1); // 3y线程启动 new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("3y终于写完了"); countDownLatch.countDown(); } }).start(); // 其他员工线程启动 for (int i = 0; i < 5; i++) { new Thread(new Runnable() { @Override public void run() { System.out.println("其他员工需要等待3y"); try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("3y终于写完了,其他员工可以开始了!"); } }).start(); } } }
2. CyclicBarrier
2.1 CyclicBarrier の概要CyclicBarrier は、すべてのスレッドが共通のバリア ポイントに到達するまで待機できるようにする同期補助です。時々相互に待機する必要がある固定サイズのスレッドが関与するプログラムでは、待機中のスレッドが解放された後に再利用できるため、バリアはに到達するまで、お互いを待機します。これは、待機中のスレッドがすべて解放されると、CyclicBarrier を再利用できるため、循環と呼ばれます (再利用できない CountDownLatch とは対照的に)cyclic
が共通のバリア ポイント- と呼ばれます。
グループ スレッドは、
使用説明:
CountDownLatch は、他のスレッドが完了するのを待つことに重点を置いています
, CyclicBarrier の焦点は、スレッドすべてのスレッドが到着 した後、実行を継続することです。 2.2 サイクリックバリアの例
例: 3 歳と彼のガールフレンドは、広州イェ上海に食事に行く約束をしました。そこで、彼らは地下鉄import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; public class Test { public static void main(String[] args) { final CyclicBarrier CyclicBarrier = new CyclicBarrier(2); for (int i = 0; i < 2; i++) { new Thread(() -> { String name = Thread.currentThread().getName(); if (name.equals("Thread-0")) { name = "3y"; } else { name = "女朋友"; } System.out.println(name + "到了体育西"); try { // 两个人都要到体育西才能发朋友圈 CyclicBarrier.await(); // 他俩到达了体育西,看见了对方发了一条朋友圈: System.out.println("跟" + name + "去夜上海吃东西~"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }).start(); } } }
一日遊んだ後、
それぞれ家に帰りました、3歳と彼のガールフレンドは、それぞれがシャワーを浴びた後におしゃべりすることに同意しました
import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; public class Test { public static void main(String[] args) { final CyclicBarrier CyclicBarrier = new CyclicBarrier(2); for (int i = 0; i < 2; i++) { new Thread(() -> { String name = Thread.currentThread().getName(); if (name.equals("Thread-0")) { name = "3y"; } else { name = "女朋友"; } System.out.println(name + "到了体育西"); try { // 两个人都要到体育西才能发朋友圈 CyclicBarrier.await(); // 他俩到达了体育西,看见了对方发了一条朋友圈: System.out.println("跟" + name + "去夜上海吃东西~"); // 回家 CyclicBarrier.await(); System.out.println(name + "洗澡"); // 洗澡完之后一起聊天 CyclicBarrier.await(); System.out.println("一起聊天"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }).start(); } } }
Semaphores are often used to restrict the number of threads than can access some (physical or logical) resource.
A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each {@link #acquire} blocks if necessary until a permit is available, and then takes it. Each {@link #release} adds a permit,potentially releasing a blocking acquirer.However, no actual permit objects are used; the {@code Semaphore} just
keeps a count of the number available and acts accordingly.
Semaphore(信号量)实际上就是可以控制同时访问的线程个数,它维护了一组"许可证"。
当调用acquire()
方法时,会消费一个许可证。如果没有许可证了,会阻塞起来
当调用release()
方法时,会添加一个许可证。
这些"许可证"的个数其实就是一个count变量罢了~
3y女朋友开了一间卖酸奶的小店,小店一次只能容纳5个顾客挑选购买,超过5个就需要排队啦~~~
import java.util.concurrent.Semaphore; public class Test { public static void main(String[] args) { // 假设有50个同时来到酸奶店门口 int nums = 50; // 酸奶店只能容纳10个人同时挑选酸奶 Semaphore semaphore = new Semaphore(10); for (int i = 0; i < nums; i++) { int finalI = i; new Thread(() -> { try { // 有"号"的才能进酸奶店挑选购买 semaphore.acquire(); System.out.println("顾客" + finalI + "在挑选商品,购买..."); // 假设挑选了xx长时间,购买了 Thread.sleep(1000); // 归还一个许可,后边的就可以进来购买了 System.out.println("顾客" + finalI + "购买完毕了..."); semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); } } }
输出结果:
反正每次只能5个客户同时进酸奶小店购买挑选。
总结:本文简单的介绍了一下Java多线程的三个同步工具类的用处以及如何用,要深入还得看源码或者查阅其他的资料。如果文章有错的地方欢迎指正,大家互相交流。
相关文章:
相关视频:
以上がJavaスレッドの3つの同期ツールに関する知識ポイントのまとめ、収集メモの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。