CountDownLatch,CyclicBarrier,Semphore区别和用途

1)CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同:

CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行;

而CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行;

另外,CountDownLatch是不能够重用的,而CyclicBarrier是可以重用的。

2)Semaphore其实和锁有点类似,它一般用于控制对某组资源的访问权限。

1.CountDownLatch 实现类似计数器的功能。比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了。
主要应用在当前现成需要在其他线程运行完成之后再执行。可以在每个线程(Thread/Runnable)内使用countDown()方法.
两种实现压测的方式:1.在当前线程中使用wait()【注意这里是wait(),不是await()】方法实现。这样才可以保证当前线程在其他线程执行完毕之后再进行执行。
2.在当前线程中循环创建线程对象的完成后执行countDown()方法,在每个线程对象的run()方法内执行await()方法。当标志量达到0后,当前线程会和创建的线程对象中await()方法后的代码争抢执行权。

主要方法:

public void await() throws InterruptedException { };   //调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };  //和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
public void countDown() { };  //将count值减1

实例
第一种方式

package com.cyan.base.CountDownLatchTest;

import java.util.concurrent.CountDownLatch;

/**
 * @Auther: Administrator
 * @Date: 2018/11/27 13:35
 * @Description:
 */
public class Test {

    @org.junit.Test
    public  void test() {
        int count = 10000;
        CountDownLatch latch = new CountDownLatch(count);
        for (int i = 0; i < count; i++) {
            new MyThread(latch).start();
        }
        try {
            latch.wait();           //!!!!!  注意这个方法
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"主方法执行啦!");
    }
}

class MyThread extends Thread {

    private CountDownLatch countDownLatch ;

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

    @Override
    public void run() {
        if (countDownLatch != null) {
            try {
                Thread.sleep(1000);
                countDownLatch.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName()+"线程对象第一个输出");
    }
}

第二种方式
调用CountDownLatch的await()方法,会使当前线程挂起,知道标示量减到0位置

package com.cyan.base.CountDownLatchTest;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Auther: Administrator
 * @Date: 2018/11/27 13:35
 * @Description:
 */
public class Test {

    public static void main(String[] asdas) {
        int count = 100;
        CountDownLatch latch = new CountDownLatch(count);
        for (int i = 0; i < count; i++) {
            MyRunnable1 myRunnable = new MyRunnable1(latch);
            new Thread(myRunnable).start();
            latch.countDown();
        }
        System.out.println(Thread.currentThread().getName()+"主方法执行啦!");
    }
}
class MyRunnable1 implements Runnable {
    CountDownLatch latch ;
    public MyRunnable1(CountDownLatch countDownLatch){
        this.latch = countDownLatch;
    }
    @Override
    public void run() {
        try {
            System.out.println(Thread.currentThread().getName()+"线程对象wait前+++++++++++++++++++++++++++的输出");
            Thread.sleep(2000);
            latch.await();      //!!!!!!!!!!!        注意这里是await()
            System.out.println(Thread.currentThread().getName()+"线程对象wait后***************************的输出");
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"线程对象第一个输出");
    }
}

2.CyclicBarrier
可以重复多次使用,CountDownLatch不可重复使用。 CyclicBarrier对象可以在一轮使用完成之后,再次重新使用
也需要指定一个int,标识当指定数量的线程都执行到此处进行等待,等数量达到预定int值时,并发执行之后的逻辑。

package com.cyan.base.CyclicBarrierTest;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Auther: Administrator
 * @Date: 2018/11/27 15:34
 * @Description:
 */
public class Test {
    public static void main(String[] args) {
        int num = 50;
        CyclicBarrier barrier = new CyclicBarrier(num);
        ExecutorService executor = Executors.newFixedThreadPool(num);
        for (int i = 0; i < num; i++) {
            executor.execute(new MyRunnable(barrier));
            System.out.println(Thread.currentThread().getName()+"循环添加线程进线程池");
        }
        System.out.println(Thread.currentThread().getName()+"主线程最后的挣扎!!!!");
    }
}
class MyRunnable implements Runnable {
    private CyclicBarrier barrier;
    public MyRunnable(CyclicBarrier barrier) {
        this.barrier = barrier;
    }
    @Override
    public void run() {
        try {
            System.out.println(Thread.currentThread().getName()+"CyclicBarrier await()执行之前!!!!");
            barrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"CyclicBarrier await()执行之后!!!!");
    }
}

3.Semaphore 信号量
主要方法: Semaphore可以控同时访问的线程个数

public void acquire() throws InterruptedException {  }     //获取一个许可
public void acquire(int permits) throws InterruptedException { }    //获取permits个许可
public void release() { }          //释放一个许可
public void release(int permits) { }    //释放permits个许可

实例:

package com.cyan.base;

import java.util.concurrent.Semaphore;

public class SemaphoreTest {
    public static void main(String[] args) {
        int a = 10;
        Semaphore semaphore = new Semaphore(2);
        for (int i = 0; i < a; i++) {
            new Thread(new MyRunnable(a,semaphore)).start();
        }
        System.out.println("当前可用许可数量为:"+semaphore.availablePermits());
    }
}
class MyRunnable implements Runnable {
    private int num;
    private Semaphore semaphore;
    public MyRunnable(int num, Semaphore semaphore) {
        this.num = num;
        this.semaphore = semaphore;
    }
    @Override
    public void run() {
        try {
            semaphore.acquire();
            System.out.println(Thread.currentThread().getName()+"工人:"+this.num+" 获取了一个锁");
            System.out.println(Thread.currentThread().getName()+"线程获取许可后许可数量为:"+semaphore.availablePermits());
            Thread.sleep(2000);
            semaphore.release();
            System.out.println(Thread.currentThread().getName()+"线程获取许可后许可数量为:"+semaphore.availablePermits());
            System.out.println(Thread.currentThread().getName()+"工人:" + this.num + " 释放了一个锁");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值