常用辅助类
CountDownLatch:减法计数器,常用于多线程中统计多线程执行完的个数。多线程在执行时,阻塞;执行完后,执行主流程。
-
countDown 减法,-1
-
await ,阻塞
CyclicBarrier:加法计数器,用法与减法计数器类似。 直译为可循环使用(Cyclic)的屏障(Barrier)。它可以让一组线程到达一个屏障(同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续工作
-
await 阻塞冲破
Semaphore:信号量,信用量主要用来保护共享资源,即资源在一个时刻只能被一个线程拥有。
-
acquire() ; 持有信号量
-
release() ; 释放信号量
实例演示
实例1、CountDownLatch
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
//新建减法构造器
CountDownLatch countDownLatch=new CountDownLatch(3);
for (int i=0;i<3;i++){
final int t=i;
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"=="+t);
//线程处理完减1
try {
TimeUnit.SECONDS.sleep(15);
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
}).start();
}
System.out.println(Thread.currentThread().getName()+"即将进入等待");
//阻塞等待,需要等待计数器为0后才能放行
countDownLatch.await();
//阻塞等待10s,等待10s后即刻放行
// countDownLatch.await(10, TimeUnit.SECONDS);
System.out.println(Thread.currentThread().getName()+"==");
}
}
结果演示:
main即将进入等待
Thread-0==0
Thread-2==2
Thread-1==1
main==
实例2、CyclicBarrier
public class CyclicBarrierDemo {
public static void main(String[] args) {
//跳过5次栅栏,则主线程继续执行
CyclicBarrier barrier=new CyclicBarrier(5,()->{
//最后一个达到5的线程执行此方法
System.out.println(Thread.currentThread().getName()+"============主线程启动");
});
for (int i=1;i<6;i++){
final int count=i;
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"============线程启动"+count);
try {
//线程完成则跳过栅栏,计数器往上累加
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
结果演示:
Thread-1============线程启动2
Thread-3============线程启动4
Thread-4============线程启动5
Thread-0============线程启动1
Thread-2============线程启动3
Thread-2============主线程启动
实例3、Semaphore
public class SemaphoreDemo {
public static void main(String[] args) {
//四个信号量,一次只能持有四个信号量,其它进入等待
Semaphore semaphore=new Semaphore(4);
for (int i=0;i<10;i++){
final int t=i;
new Thread(()->{
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"======"+t+"==抢到信号量=");
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();
System.out.println(Thread.currentThread().getName()+"======"+t+"==释放信号量=");
}
}).start();
}
结果演示:
Thread-0======0
Thread-2======2
Thread-3======3
Thread-1======1
Thread-4======4
Thread-7======7
Thread-6======6
Thread-5======5
Thread-9======9
Thread-8======8
使用场景分析
CountDownLatch:某一个线程等待其它线程执行完毕后再执行
CyclicBarrier: CyclicBarrier可以用于多线程计算数据,最后合并计算结果的应用场景。
Semaphore: 用于几个消费线程需要同时用到信号量,但信号量不足需要进行等待的情况。例如 银行有3个柜面,10个用户需要办理业务,最多只能执行3个用户并行;3个柜面就是信号量,10个用户就是消费线程。