juc学习六(CountDownLatchCyclicBarrier和Semaphore)
Posted mabaoying
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了juc学习六(CountDownLatchCyclicBarrier和Semaphore)相关的知识,希望对你有一定的参考价值。
CountDownLatch
CountDownLatch闭锁是在java1.5被引入,存在于java.util.cucurrent包下。
CountDownLatch是一个同步辅助类,让一些线程阻塞直到另一些线程完成一系列操作后才被唤醒。CountDownLatch是通过一个计数器来实现的,计数器的初始值是线程的数量。
CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,调用线程会被阻塞。其它线程调用countDown方法会将计数器减1(调用countDown方法的线程不会阻塞),当计数器的值变为零时,表示所有线程都执行完毕,因调用await方法被阻塞的线程会被唤醒,继续执行。
当我们在完成某些运算时,只有其他所有线程运算全部完成,当前运算才继续执行,就需要使用CountDownLatch闭锁。
示例:
public class CountDownLatchDemo { public static void main(String[] args) throws InterruptedException { //构造参数count为计数值 CountDownLatch countDownLatch=new CountDownLatch(5); for(int i=1;i<=5;i++){ new Thread(()-> { System.out.println(Thread.currentThread().getName() + " 开始工作"); //将count值减1 countDownLatch.countDown(); }).start(); } //调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行 countDownLatch.await(); System.out.println(Thread.currentThread().getName()+" 完成工作"); } }
CycliBarrier
CyclicBarrier字面意思就是可循环使用的屏障。就是让一组线程到达一个屏障(也叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过CyclicBarrier的await方法。
使用场景:可以用于多线程计算数据,最后合并计算结果的场景。
构造方法
public CyclicBarrier(int parties) //parties 是参与线程的个数,Runnable 参数,这个参数的意思是最后一个到达线程要做的任务 public CyclicBarrier(int parties, Runnable barrierAction)
示例:
/** * 一个线程组的线程需要等待所有线程完成任务后再继续执行下一次任务 */ 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 tmpI=i; new Thread(()->{ System.out.println(Thread.currentThread().getName()+" 执行线程:"+tmpI+"成功"); try { //线程调用 await() 表示自己已经到达栅栏 cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); //BrokenBarrierException 表示栅栏已经被破坏,破坏的原因可能是其中一个线程 await() 时被中断或者超时 } catch (BrokenBarrierException e) { e.printStackTrace(); } },String.valueOf(i)).start(); } } }
1.countDownLatch是一个计数器,线程完成一个记录一个,计数器递减,只能只用一次
2.CyclicBarrier的计数器更像一个阀门,需要所有线程都到达,然后继续执行,计数器递增,提供reset功能,可以多次使用
Semaphore
Semaphore 是一个计数信号量,主要用于两个目的,一个是用于多个共享资源的互斥使用,另一个用于并发线程的控制。
示例:
/** * 5个线程抢占2个资源,只允许两个线程同时访问 */ public class SemaphoreDemo { public static void main(String[] args) { //信号量,只允许2个线程同时访问,其他线程只能等待 Semaphore semaphore=new Semaphore(2); for(int i=1;i<=5;i++){ new Thread(()->{ try { //从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断 semaphore.acquire(); System.out.println(Thread.currentThread().getName()+" 抢到资源"); //暂停三秒 TimeUnit.SECONDS.sleep(3); System.out.println(Thread.currentThread().getName()+" 3秒后释放资源"); //释放一个许可,将其返回给信号量 semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } },String.valueOf(i)).start(); } } }
以上是关于juc学习六(CountDownLatchCyclicBarrier和Semaphore)的主要内容,如果未能解决你的问题,请参考以下文章