CountDownLatch/CyclicBarrier/Semaphore/Exchanger使用过吗?

四者都是jdk1.5的新特性

 

一、CountDownLatch

举例:老师等学生到齐后上课
1、涉及线程:1个老师线程,多个学生线程。
2、多个学生线程共用一个new CountDownLatch()对象,当来了一个学生后,该学生(线程)就调用countDownLatch.countDown();
所以需要给学生线程的构造方法指定要使用的countDownLatch(且必须是同一个);
3、老师(主线程)调用countDownLatch.await()进行等待所有学生的到来(都到来后,才会继续执行老师线程)

自己写的代码

public class AboutCountDownLatchAndCyclicBarrier {

    static class MyCountDownLatch implements Runnable{
        private CountDownLatch countDownLatch;

        public MyCountDownLatch(CountDownLatch countDownLatch){
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            try {
                TimeUnit.SECONDS.sleep(1);
                System.out.println(Thread.currentThread().getName() + "执行了一个countDownLatch");
                countDownLatch.countDown();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } 
    }

    public static void main(String[] args) {
        int sumStudent = 5;
        CountDownLatch latch = new CountDownLatch(sumStudent);
        for (int i = 0; i < sumStudent; i++) {
            new Thread(new MyCountDownLatch(latch), String.valueOf(i)).start(); //所有学生线程都操纵同一个CountDownLatch对象
        }
        System.out.println("现在等待" + sumStudent + "个学生到齐");
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(sumStudent + "个学生都到齐了,老师开始上课");
    }
}

二、CyclicBarrier

举例:几个员工翻墙,一堵墙大家都翻过了,才能翻下一堵墙。
1、涉及线程:多个员工。(相互牵制,等到大家都完成了,大家再一起去做下一件事)
2、多个人共用一个new CyclicBarrier(employeeSum),当一个员工翻过后,就调用cyclicBarrier.await(),等待其他员工翻过来;
所以需要给员工线程的构造方法指定要使用的cyclicBarrier(且必须是同一个);
3、主线程启动这些线程后,什么都不用干,因为这里不存在主线程等来员工翻过所有墙后需要干些什么。

public class CyclicBarrierTest {

    private static class MyRunnable implements Runnable{
        private CyclicBarrier barrier;

        public MyRunnable(CyclicBarrier barrier){
            this.barrier = barrier;
        }

        @Override
        public void run() {
            for(int i = 0; i < 3; i++) {
                try {
                    Random rand = new Random();
                    int randomNum = rand.nextInt((3000 - 1000) + 1) + 1000;//产生1000到3000之间的随机整数
                    Thread.sleep(randomNum);
                    System.out.println(Thread.currentThread().getName() + ", 通过了第"+i+"个障碍物, 使用了 "+((double)randomNum/1000)+"s");
                    this.barrier.await();//(相互牵制,等到大家都完成了,大家再一起去做下一件事)
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(3);
        for(int i = 0; i < barrier.getParties(); i++){
            new Thread(new MyRunnable(barrier), "队友"+i).start();
        }
        System.out.println("main function is finished."); //主线程启动这些线程后,什么都不用干
    }
}

三、Semaphore

semaphore.acquire();
semapore.release();
详见下面的Semaphore

小总结:
三者统一用法,都是
CountDownLatch latch = new CountDownLatch(几个);
CyclicBarrier barrier = new CyclicBarrier(几个);
Semaphore semaphore = new Semaphore(几个);
然后
for(int i = 0; i<几个; i++){
    new Thread()
}

 


一、CountDownLatch(倒计时锁)-jdk1.5

 

在jdk1.5之前,使用join()来实现类似的功能;(学生线程join进来,它们都执行完后,主线程(老师)才能继续执行)

在jdk1.5之后,用CountDownLatch。

 

在JUC包下

它有几个方法:

new CountDownLatch(int)

countDown()

await()

 

在CountDownLatch中,有的线程在倒计时countDown(),有的线程在等待倒计时结束await()

倒计时的线程调用countDown()并不会阻塞,调用await()等待倒计时结束的线程(即main线程)会自我阻塞。计数器为零时,main线程会被唤醒并继续执行。

 

举个例,关于CountDownLatch的最基本使用:

其他6个线程执行完毕(被灭后)后,让counDownLatch调用一下countDown()方法

统一华夏的那步操作在counDownLatch调用await()方法后执行。

一共有几个国要被灭,写在构造函数中确定

 

二、CyclicBarrier(循环屏障)-jdk1.5

怎么理解上面这句话: 七个人到齐了才开会。(即等待的是这一个个线程,而CountDownLatch等待的是最后这个主线程)
做的是加法,而CountDownLatch做的是减法。
CyclicBarrier在JUC包下

召唤神龙的那步操作在CyclicBarrier的构造函数中写;
集齐龙珠的线程收集了自己该收集的龙珠操作后,在自己线程体内让 cyclicBarrier对象调用一下await()方法;
其他就不用做什么了。
一共要收集多少颗龙珠,写在构造函数中确定 

 

三、Semaphore-jdk1.5

Semaphore 是一个计数信号量,必须由获取它的线程释放。
当资源数远大于实际需求的时候,Semaphore实际限制的是可以访问某些资源的线程数量
当资源数远小于实际需求的时候,Semaphore实际是说明了可以访问的某些资源的数量
可以代替synchronized和lock

demo:六个车(线程)抢3个车位(资源)

 semaphore是可伸缩的,可变大可变小

 

补充:
四、Exchanger-jdk1,5

Exchanger 是 JDK 1.5 开始提供的一个用于两个工作线程之间交换数据的封装工具类,简单说就是一个线程在完成一定的事务后想与另一个线程交换数据,则第一个先拿出数据的线程会一直等待第二个线程,直到第二个线程拿着数据到来时才能彼此交换对应数据。其定义为 Exchanger<V> 泛型类型,其中 V 表示可交换的数据类型,对外提供的接口很简单,具体如下:
* Exchanger():无参构造方法。
* V exchange(V v):等待另一个线程到达此交换点(除非当前线程被中断),然后将给定的对象传送给该线程,并接收该线程的对象。
* V exchange(V v, long timeout, TimeUnit unit):等待另一个线程到达此交换点(除非当前线程被中断或超出了指定的等待时间),然后将给定的对象传送给该线程,并接收该线程的对象。

可以看出,当一个线程到达 exchange 调用点时,如果其他线程此前已经调用了此方法,则其他线程会被调度唤醒并与之进行对象交换,然后各自返回;如果其他线程还没到达交换点,则当前线程会被挂起,直至其他线程到达才会完成交换并正常返回,或者当前线程被中断或超时返回。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值