前言:
本文内容:CountDownLatch、CyclicBarrier、Semaphore
推荐免费JUC并发编程视频:【狂神说Java】JUC并发编程最新版通俗易懂_哔哩哔哩_bilibili
CountDownLatch
允许一个或多个线程等待直到其他线程中执行的一组操作完成的同步辅助
减法计数器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| package com.jokerdig.add;
import java.util.concurrent.CountDownLatch;
public class CountDownLatchDemo { public static void main(String[] args) throws InterruptedException { CountDownLatch downLatch = new CountDownLatch(5);
for (int i= 1;i<=5;i++){ new Thread(()->{ System.out.println(Thread.currentThread().getName()+"->end"); downLatch.countDown(); }).start(); } downLatch.await();
System.out.println("计数器已经归零"); } }
|
运行结果
1 2 3 4 5 6
| Thread-2->end Thread-3->end Thread-0->end Thread-1->end Thread-4->end 计数器已经归零
|
原理
countDown();
数量减1
- await();` 等待计数器归零在向下执行
每次线程调用countDown()
数量减1,计数器变为0,await()
就会被唤醒,继续执行。
CyclicBarrier
允许一组线程全部等待彼此达到共同屏屏障点的同步辅助,循环阻塞在涉及固定大小的线程中很有用,这些线程必须偶尔等待彼此;屏障被称为循环,因为它可以在等待线程被释放之后重新使用。
加法计数器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| package com.jokerdig.add;
import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierDemo { public static void main(String[] args) { CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{ System.out.println("召唤神龙!"); });
for(int i =1;i<=7;i++){ final int temp = i; new Thread(()->{ System.out.println(Thread.currentThread().getName()+"收集第"+temp+"颗龙珠"); try { cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); }
}).start(); } } }
|
运行结果
1 2 3 4 5 6 7 8 9 10
| Thread-0收集第1颗龙珠 Thread-5收集第6颗龙珠 Thread-2收集第3颗龙珠 Thread-1收集第2颗龙珠 Thread-6收集第7颗龙珠 Thread-3收集第4颗龙珠 Thread-4收集第5颗龙珠 召唤神龙!
Process finished with exit code 0
|
Semaphore
Semaphore:信号量
一个计数信号量,在概念上,信号量维持一组许可证,如果有必要,每个acquire()
都会阻塞,直到许可证可用,然后才能使用它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package com.jokerdig.add;
import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit;
public class SemaphoreDemo { public static void main(String[] args) { Semaphore semaphore = new Semaphore(3);
for (int i=1;i<=6;i++){ new Thread(()->{ try { semaphore.acquire(); System.out.println(Thread.currentThread().getName()+"抢到了车位"); TimeUnit.SECONDS.sleep(2); System.out.println(Thread.currentThread().getName()+"离开了车位");
} catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); } },String.valueOf(i)).start(); } } }
|
运行结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 2抢到了车位 1抢到了车位 3抢到了车位 1离开了车位 2离开了车位 4抢到了车位 5抢到了车位 3离开了车位 6抢到了车位 6离开了车位 4离开了车位 5离开了车位
Process finished with exit code 0
|
原理
acquire()
得到,如果位置已经满了,开始等待,直到被释放为止;
release()
释放,会将当前的信号量释放+1,然后唤醒等待的线程;
作用:多个共享资源互斥的时候使用,并发限流,控制最大线程数!