Java并发包(1):CountDownLatch、CyclicBarrier、Semaphore

1.CountDownLatch
CountDownLatch.wait()会使当前线程阻塞,直到CountDownLatch中的计数器递减完毕后继续执行。

public class CountDownLatchDemo {

private final static Logger log = Logger.getLogger(AtomicIntegerCyclicBarrierDemo.class);

public static void main(String[] args) {
        final CountDownLatch latch = new CountDownLatch(2);
        new Thread(){
                public void run() {
                                log.info(Thread.currentThread().getName() + " running");
                                latch.countDown();
                };
        }.start();
        new Thread(){
                public void run() {
                        try {
                                log.info(Thread.currentThread().getName() + " running");
                                Thread.sleep(5000);
                                latch.countDown();
                        } catch (InterruptedException e) {
                                e.printStackTrace();
                        }
                };
        }.start();
        try {
                latch.await();
                log.info("all finished");
        } catch (InterruptedException e) {
                e.printStackTrace();
        }
    }
}

运行日志:
2019-10-24 09:23:24,069-[HL][17] INFO Thread-0 AtomicIntegerCyclicBarrierDemo - Thread-0 running
2019-10-24 09:23:24,075-[HL][24] INFO Thread-1 AtomicIntegerCyclicBarrierDemo - Thread-1 running
2019-10-24 09:23:29,076-[HL][34] INFO main AtomicIntegerCyclicBarrierDemo - all finished
见第三条09:23:29,主线程一直阻塞直到线程2完成后才继续向下执行



2.CyclicBarrier
CyclicBarrier可以比做一个阻拦器,当同时阻塞的线程数达到某个个数时,才会将所有线程放行,这里结合 同样是并发包中的AtomicInteger实现了一个案例,AtomicInteger时基于CAS实现的乐观锁,也就是说当修改值与预期值不一致时,AtomicInteger会修改失败并重试,也就是说当我们用多个线程同时累加,在所有线程执行完毕之后,结果是安全的

public class AtomicIntegerCyclicBarrierDemo {

private final static Logger log = Logger.getLogger(AtomicIntegerCyclicBarrierDemo.class);

private final static AtomicInteger count = new AtomicInteger(0);

private final static int THREAD_COUNT = 100;

    public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT, new Runnable() {
            public void run() {
                log.info(String.format("result = %s", count.get()));
            }
        });
        for (int i = 0; i < THREAD_COUNT; i++) {
            new Task(barrier, count).start();
        }
    }
}

class Task extends Thread {

private CyclicBarrier cyclicBarrier;

private AtomicInteger count;

public Task(CyclicBarrier cyclicBarrier, AtomicInteger count) {
    this.cyclicBarrier = cyclicBarrier;
    this.count = count;
}

@Override
public void run() {
    super.run();
    try {
        count.addAndGet(2);
        cyclicBarrier.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (BrokenBarrierException e) {
        e.printStackTrace();
    }
}
}

运行日志:
2019-10-24 09:40:11,961-[HL][22] INFO Thread-99 AtomicIntegerCyclicBarrierDemo - result = 200
CyclicBarrier帮助我们在所有线程执行完之后,进行结果的打印



3.Semaphore
Semaphore用来控制可同时运行的线程数,比如一个案例,我们有一些模型转换任务,为了控制计算资源占用,只允许同时3个线程同时运行,每当一个线程运行完才能空出一个槽位给新的线程运行,下面见代码

public class SemaphoreDemo {

private final static int THREAD_COUNT = 8 ;

public static void main(String[] args) {
    Semaphore semaphore = new Semaphore(3);
    for(int i = 0; i < THREAD_COUNT ; i++) {
        try {
            Thread.sleep(2000);
            new Task2(i, semaphore).start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
}

class Task2 extends Thread{

private final static Logger log = Logger.getLogger(Task2.class);

private int num;

private Semaphore semaphore;

public Task2(int num,Semaphore semaphore){
    this.num = num;
    this.semaphore = semaphore;
}

@Override
public void run() {
    try {
        semaphore.acquire();
        log.info(String.format("task(id = %s) opeater", this.num));
        Thread.sleep(10000);
        log.info(String.format("task(id = %s) finished", this.num));
        semaphore.release();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
}

运行日志:
2019-10-24 09:51:49,180-[HL][39] INFO Thread-0 Task2 - task(id = 0) opeater
2019-10-24 09:51:51,150-[HL][39] INFO Thread-1 Task2 - task(id = 1) opeater
2019-10-24 09:51:53,151-[HL][39] INFO Thread-2 Task2 - task(id = 2) opeater
2019-10-24 09:51:59,190-[HL][41] INFO Thread-0 Task2 - task(id = 0) finished
2019-10-24 09:51:59,190-[HL][39] INFO Thread-3 Task2 - task(id = 3) opeater
2019-10-24 09:52:01,151-[HL][41] INFO Thread-1 Task2 - task(id = 1) finished
2019-10-24 09:52:01,152-[HL][39] INFO Thread-4 Task2 - task(id = 4) opeater
2019-10-24 09:52:03,151-[HL][41] INFO Thread-2 Task2 - task(id = 2) finished
2019-10-24 09:52:03,159-[HL][39] INFO Thread-5 Task2 - task(id = 5) opeater

原文地址:https://blog.51cto.com/13665344/2445202

时间: 2024-10-10 08:48:57

Java并发包(1):CountDownLatch、CyclicBarrier、Semaphore的相关文章

并发包下常见的同步工具类详解(CountDownLatch,CyclicBarrier,Semaphore)

目录 1. 前言 2. 闭锁CountDownLatch 2.1 CountDownLatch功能简介 2.2 使用CountDownLatch 2.3 CountDownLatch原理浅析 3.循环屏障CyclicBarrier 3.1 CyclicBarrier功能简介 3.2 使用CyclicBarrier 3.3 CyclicBarrier原理浅析 4. 信号量Semaphore 4.1 Semaphore功能简介 4.2 使用Semaphore进行最大并发数的控制 4.3 Semaph

CountDownLatch/CyclicBarrier/Semaphore 使用过吗?

CountDownLatch/CyclicBarrier/Semaphore 使用过吗?下面详细介绍用法: 一,CountDownLatch  背景; countDownLatch(同步援助)是在java1.5被引入,跟它一起被引入的工具类还有CyclicBarrier(同步援助).Semaphore(计数信号量).concurrentHashMap和BlockingQueue(阻塞队列). 存在于java.util.cucurrent包下.   概念理解: 让一些线程阻塞,直到另外一些线程完成

CountDownLatch CyclicBarrier Semaphore 比较

document CountDownLatch A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes. CyclicBarrier A synchronization aid that allows a set of threads to all wait for each other to

Join,CountDownLatch,CyclicBarrier,Semaphore和Exchanger

CountDownLatch允许一个或者多个线程等待其他线程完成操作,之后再对结果做统一处理: 适用场景,分布式系统中对多个微服务的调用,并发执行并且必须等待全部执行完成才能继续执行后续操作: 其实在java中默认的实现是join()方法,join()方法主要的作用是当前线程必须等待直到join线程执行完成之后才能继续执行后续的操作, 其本质就是轮询判断join线程是否存活,如果存活则主线程继续等待,否则,通过调用this.notifyAll()方法来继续执行主线程. 实例代码如下: publi

Java并发包中CountDownLatch的工作原理、使用示例

1. CountDownLatch的介绍 CountDownLatch是一个同步工具,它主要用线程执行之间的协作.CountDownLatch 的作用和 Thread.join() 方法类似,让一些线程阻塞直到另一些线程完成一系列操作后才被唤醒.在直接创建线程的年代(Java 5.0 之前),我们可以使用 Thread.join().在线程池出现后,因为线程池中的线程不能直接被引用,所以就必须使用 CountDownLatch 了. CountDownLatch主要有两个方法,当一个或多个线程调

java并发之CountDownLatch、Semaphore和CyclicBarrier

JAVA并发包中有三个类用于同步一批线程的行为,分别是CountDownLatch.Semaphore和CyclicBarrier. CountDownLatch CountDownLatch是一个计数器闭锁,主要的功能就是通过await()方法来阻塞住当前线程,然后等待计数器减少到0了,再唤起这些线程继续执行. 这个类里主要有两个方法,一个是向下减计数器的方法:countdown(),其实现的核心代码如下: public boolean tryReleaseShared(int release

转发---[沧海拾遗]java并发之CountDownLatch、Semaphore和CyclicBarrier

JAVA并发包中有三个类用于同步一批线程的行为,分别是CountDownLatch.Semaphore和CyclicBarrier. CountDownLatch CountDownLatch是一个计数器闭锁,主要的功能就是通过await()方法来阻塞住当前线程,然后等待计数器减少到0了,再唤起这些线程继续执行. 这个类里主要有两个方法,一个是向下减计数器的方法:countdown(),其实现的核心代码如下: public boolean tryReleaseShared(int release

Java并发编程:CountDownLatch、CyclicBarrier和Semaphore (总结)

下面对上面说的三个辅助类进行一个总结: 1)CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同: CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它才执行: 而CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行: 另外,CountDownLatch是不能够重用的,而CyclicBarrier是可以重用的. 2)Semaphore其实和锁有点类似,它一般用于控制对某组资源的访问权

Java多线程20:多线程下的其他组件之CountDownLatch、Semaphore、Exchanger

前言 在多线程环境下,JDK给开发者提供了许多的组件供用户使用(主要在java.util.concurrent下),使得用户不需要再去关心在具体场景下要如何写出同时兼顾线程安全性与高效率的代码.之前讲过的线程池.BlockingQueue都是在java.util.concurrent下的组件,Timer虽然不在java.util.concurrent下,但也算是.后两篇文章将以例子的形式简单讲解一些多线程下其他组件的使用,不需要多深刻的理解,知道每个组件大致什么作用就行. 本文主要讲解的是Cou