関連する無料学習の推奨事項: Java 基本チュートリアル
一般的に使用される補助クラス
1.CountDownLatch
# #1.2.例: モニターがドアをロックする 問題
問題の説明: 夕方に勉強している 7 人の学生がいると仮定します。鍵はモニターの手にあり、彼はドアをロックする責任があります。 。モニターは、照明を消してドアをロックする前に、全員がいなくなるまで待たなければなりません。この6人の生徒は順番が乱れており、いつ退出したのかも分からない。 6 人の学生はそれぞれ独自の自習授業を受け、間に交流はありませんでした。 6 人の生徒が通常のスレッドで、モニターがメイン スレッドであると仮定します。メイン スレッドの実行が完了する前に、大量のスレッドの実行が完了するまでメイン スレッドを待機させるにはどうすればよいでしょうか?public class CountDownLatchDemo { public static void main(String[] args) { // TODO Auto-generated method stub for(int i=1;i{ System.out.println(Thread.currentThread().getName()+"\t离开教室"); },String.valueOf(i)).start(); } System.out.println(Thread.currentThread().getName()+"\t班长关门走人"); }}
最後に先生を3人で閉じ込めてしまいますが、これは事故の原因になるので絶対にダメです。
1.2 で CountDownLatch クラスを使用する必要があります。CountDownLatch クラスの概要:
1.2.1 CountDownLatch の概念
CountDownLatch は、複数のスレッド間の同期を調整したり、(相互排他として機能するのではなく) スレッド間で通信したりするために使用される同期ツール クラスです。
CountDownLatch を使用すると、スレッドは の実行を続行する前に、他のスレッドが作業を完了するのを待つことができます。 カウンターを使用して実装します。カウンタの初期値はスレッド数です。各スレッドがタスクを完了すると、カウンタ値が 1 ずつ減ります。カウンタ値が 0 の場合、すべてのスレッドがいくつかのタスクを完了し、CountDownLatch で待機しているスレッドが次のタスクの実行を再開できることを意味します。
CountDownLatch の説明: count count、count down、start Latch1.2.3 CountDownLatch の使用法
特定のスレッドは、 starting 実行する前に、n 個のスレッドが実行を完了するまで待ちます。 CountDownLatch カウンタを新しい CountDownLatch(n) に初期化します。タスク スレッドが実行を完了するたびに、カウンタは 1 countdownLatch.countDown() ずつ減分されます。カウンタ値が 0 になると、CountDownLatch のスレッド await() が起動されます。典型的なアプリケーション シナリオでは、サービスを開始するときに、メイン スレッドは実行を続行する前に複数のコンポーネントがロードされるのを待つ必要があります。 CountDownLatch の基礎となるコンストラクターのソース コード
public CountDownLatch(int count) { if (count <p>1.3.CountDownLatch のケース: <strong></strong></p><pre class="brush:php;toolbar:false">public static void main(String[] args) throws InterruptedException { //6个同学正在上自习,每个人就有一个1计数器,走1个数字减1,main线程启动,必须要等计时器从6变成0,才能开始。 CountDownLatch countDownLatch=new CountDownLatch(6); for(int i=1;i{ System.out.println(Thread.currentThread().getName()+"\t离开教室"); countDownLatch.countDown(); //计算减少一个 },String.valueOf(i)).start(); } countDownLatch.await(); //班长前面需要被阻塞 System.out.println(Thread.currentThread().getName()+"\t班长关门走人"); }
ここで全員がいつ出発するかはわかりませんが、分隊長が毎回最後に出発することは保証できます。
1.4. 原理の概要
CountDownLatch には主に 2 つのメソッドがあり、1 つ以上のスレッドが await メソッドを呼び出すと、これらのスレッドはブロックされます。 他のスレッドが countDown メソッドを呼び出すと、カウンタが 1 減算されます (countDown メソッドを呼び出したスレッドはブロックされません)
カウンタ値が 0 になると、await メソッドによってブロックされていたスレッドが目覚めて実行されますつづきます。
2.CyclicBarrier
2.1. CyclicBarrier の紹介
サイクル サイクル、バリア バリア。 文字通りの意味からすると、このクラスの中国語の意味は「循環フェンス」です。大雑把に言えば、リサイクル可能なバリアを意味します。
その機能は、次のステップに進む前に、すべてのスレッドが完了するまで待機することです。 モニターがドアを閉める上記の例では、カウントダウンが行われていますが、ここではその逆で、加算が行われ、その数値に達すると開始されます。
たとえば、全員が揃ったら、会議を再開します。 、たとえば、人生と同じように、私たちは同僚を会議に招待します。早く到着する同僚もいれば、遅れて到着する同僚もいるかもしれません。ただし、会議では、全員が到着するまで待たなければならないと規定されています。正式に会議を開きます。ここでの同僚はスレッドであり、会議は CyclicBarrier です。
public CyclicBarrier(int parties)public CyclicBarrier(int parties, Runnable barrierAction)
partiesは参加スレッドの数です 2番目の構築メソッドにはRunnableパラメータがあり、これは最後に到達するスレッドを意味します。スレッドによって実行されるタスク
2.2. ケース: ドラゴンボールを 7 つ集めてドラゴンを召喚する
public static void main(String[] args) { // TODO Auto-generated method stub CyclicBarrier cyclicBarrier=new CyclicBarrier(7,()->{System.out.println("召唤神龙");}); for(int i=1;i{ System.out.println(Thread.currentThread().getName()+"\t收集到第"+tempInt+"颗龙珠"); try { //某个线程收集到了龙珠只能先等着,等龙珠收齐了才能召唤神龙 cyclicBarrier.await(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } },String.valueOf(i)).start();; } }
截图
3.Semophore
3.1.Semophore简介
前面讨论的问题都是多对一的问题,我们现在可以讨论多对多的问题了。
假设有7个兄弟开车上班,而现在只有4个车位。7部车并列开进4个车位,每个车停了多长时间未知,资源被占用完了。假设有一个车只停了2s,那么它走了,外面的车又可以进来了。走一个进一个,最后全部都可以进去。而semophore就是控制多线程的并发策略。
简单理解来说,Semaphore:信号量主要用于两个目的:一个是用于多个共享资源的互斥使用;另一个用于并发线程数量的控制。
Semaphore类有两个重要方法
1、semaphore.acquire();
请求一个信号量,这时候信号量个数-1,当减少到0的时候,下一次acquire不会再执行,只有当执行一个release()的时候,信号量不为0的时候才可以继续执行acquire
2、semaphore.release();
释放一个信号量,这时候信号量个数+1,
3.2.抢车位问题
public static void main(String[] args) { //模拟6部车抢3个空车位 Semaphore semaphore=new Semaphore(3);//模拟资源类,有3个空车位 for(int i=1;i{ try { //谁先抢到了,谁就占一个车位,并且要把semaphore中的资源数减1 semaphore.acquire(); System.out.println(Thread.currentThread().getName()+"\t抢占到了车位"); TimeUnit.SECONDS.sleep(3); System.out.println(Thread.currentThread().getName()+"\t离开了车位"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ //释放车位 semaphore.release(); } },String.valueOf(i)).start(); } }
运行结果截图:
3.3.原理总结
在信号量上我们定义两种操作:
acquire(获取)当一个线程调用acquire操作时,它要么通过成功获取信号量(信号量减1),要么一直等待下去,直到有线程释放信号量,或超时。
release(释放)实际上会将信号量的值加1,然后唤醒等待的线程。
信号量主要用于两个目的:一个是用于多个共享资源的互斥使用;另一个用于并发线程数量的控制
如果把资源数从3变成1了,此时就等价于synchronized。
以上がJava 並行プログラミング、一般的に使用される補助クラスの紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。