Cyclicbarrier和Countdownlatch对比和使用
2018-03-03 16:28
465 查看
CountDownLatch
包名: java.util.concurrent用途:等待其他线程执行完毕后执行
主要方法:
构造器
/** * Constructs a {@code CountDownLatch} initialized with the given count. * * @param count the number of times {@link #countDown} must be invoked * before threads can pass through {@link #await} * @throws IllegalArgumentException if {@code count} is negative */ public CountDownLatch(int count) { if (count < 0) throw new IllegalArgumentException("count < 0"); this.sync = new Sync(count); }
线程等待 可以设置超时时间
public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1); } public boolean await(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout)); }
计数器减1 每个线程执行完调用一次方法,直到count的值为0
public void countDown() { sync.releaseShared(1); }
使用demo
自己实现一个Runnable,传入CountDownLatch参数/** * 描述: * 使用countdownlatch * * @author Kipeng Huang * @create 2018-03-03 下午1:28 */ public class CountRunnable implements Runnable { private CountDownLatch countDownLatch; public CountRunnable(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } /** * countDownLatch.countDown(); 放在finally中执行 */ @Override public void run() { try { //打印线程名称 System.out.println(Thread.currentThread().getName()); System.out.println("开始处理数据..."); Thread.sleep(3000L); System.out.println("数据处理完毕..."); } catch (InterruptedException e) { e.printStackTrace(); } finally { countDownLatch.countDown(); } } }
测试main方法
/** * 描述: * * @author Kipeng Huang * @create 2018-03-03 下午1:32 */ public class TestCountDownLatch { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(20); //可以定义线程名称规则 ThreadFactory namedThreadFactory = new ThreadFactoryBuilder() .setNameFormat("demo-pool-%d").build(); //使用阿里Java规范自己创建线程池 ExecutorService threadPool = new ThreadPoolExecutor(4, 20, 1000L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy()); for (int i = 0; i < 20; i++) { threadPool.execute(new CountRunnable(countDownLatch)); } countDownLatch.await(); System.out.println("全部数据处理完毕"); threadPool.shutdown(); } }
执行结果
demo-pool-0 开始处理数据... demo-pool-1 开始处理数据... demo-pool-2 开始处理数据... demo-pool-3 开始处理数据... 数据处理完毕... 数据处理完毕... demo-pool-1 demo-pool-0 开始处理数据... 开始处理数据... 数据处理完毕... demo-pool-2 开始处理数据... 数据处理完毕... demo-pool-3 开始处理数据... 数据处理完毕... 数据处理完毕... demo-pool-0 开始处理数据... demo-pool-1 开始处理数据... 数据处理完毕... demo-pool-2 开始处理数据... 数据处理完毕... demo-pool-3 开始处理数据... 数据处理完毕... 数据处理完毕... demo-pool-0 开始处理数据... demo-pool-1 开始处理数据... 数据处理完毕... demo-pool-2 开始处理数据... 数据处理完毕... demo-pool-3 开始处理数据... 数据处理完毕... demo-pool-0 开始处理数据... 数据处理完毕... demo-pool-1 开始处理数据... 数据处理完毕... demo-pool-2 开始处理数据... 数据处理完毕... demo-pool-3 开始处理数据... 数据处理完毕... 数据处理完毕... 数据处理完毕... 数据处理完毕... 全部数据处理完毕 Process finished with exit code 0
从执行结果可以看出,主线程一直阻塞,知道count为0的时候执行
CyclicBarrier
包名: java.util.concurrent用途: 通过它可以实现让一组线程等待至某个状态之后全部同时执行
主要的两个构造方法
/** * @param parties 表示有多少线程阻塞在这里等待 * @param barrierAction 满足条件后执行这个任务 */ public CyclicBarrier(int parties, Runnable barrierAction) { if (parties <= 0) throw new IllegalArgumentException(); this.parties = parties; this.count = parties; this.barrierCommand = barrierAction; } /** * Creates a new {@code CyclicBarrier} that will trip when the * given number of parties (threads) are waiting upon it, and * does not perform a predefined action when the barrier is tripped. * * @param parties 表示有多少线程阻塞在这里等待 * @throws IllegalArgumentException if {@code parties} is less than 1 */ public CyclicBarrier(int parties) { this(parties, null); }
使用demo
/** * 描述: * * @author Kipeng Huang * @create 2018-03-03 下午2:10 */ public class CycleBarrierRunnable implements Runnable { private CyclicBarrier cyclicBarrier; public CycleBarrierRunnable(CyclicBarrier cyclicBarrier) { this.cyclicBarrier = cyclicBarrier; } @Override public void run() { System.out.println("当前线程名:" + Thread.currentThread().getName()); try { Thread.sleep(2000); cyclicBarrier.await(); System.out.println("线程" + Thread.currentThread().getName() + "执行完毕"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } }
/** * 描述: * * @author Kipeng Huang * @create 2018-03-03 下午2:21 */ public class BarrierTest { public static void main(String[] args) { ThreadFactory threadFactory = new ThreadFactoryBuilder() .setNameFormat("demo-pool-%d") .build(); ExecutorService threadPool = new ThreadPoolExecutor(20, 20, 2000L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1024), threadFactory, new ThreadPoolExecutor.AbortPolicy()); CyclicBarrier cyclicBarrier = new CyclicBarrier(20); for (int i = 0; i < 20; i++) { threadPool.execute(new CycleBarrierRunnable(cyclicBarrier)); } cyclicBarrier.reset(); System.out.println("主线程程序执行"); threadPool.shutdown(); } }
当前线程名:demo-pool-0 当前线程名:demo-pool-1 当前线程名:demo-pool-2 当前线程名:demo-pool-3 当前线程名:demo-pool-4 当前线程名:demo-pool-5 当前线程名:demo-pool-6 当前线程名:demo-pool-7 当前线程名:demo-pool-8 当前线程名:demo-pool-9 当前线程名:demo-pool-10 当前线程名:demo-pool-11 当前线程名:demo-pool-12 当前线程名:demo-pool-13 当前线程名:demo-pool-14 当前线程名:demo-pool-15 当前线程名:demo-pool-16 当前线程名:demo-pool-17 当前线程名:demo-pool-18 主线程程序执行 当前线程名:demo-pool-19 线程demo-pool-19执行完毕 线程demo-pool-1执行完毕 线程demo-pool-3执行完毕 线程demo-pool-4执行完毕 线程demo-pool-8执行完毕 线程demo-pool-0执行完毕 线程demo-pool-11执行完毕 线程demo-pool-10执行完毕 线程demo-pool-9执行完毕 线程demo-pool-6执行完毕 线程demo-pool-7执行完毕 线程demo-pool-5执行完毕 线程demo-pool-2执行完毕 线程demo-pool-17执行完毕 线程demo-pool-18执行完毕 线程demo-pool-16执行完毕 线程demo-pool-15执行完毕 线程demo-pool-13执行完毕 线程demo-pool-14执行完毕 线程demo-pool-12执行完毕 Process finished with exit code 0
注意事项
如果线程池核心线程数小于CyclicBarrier的数量,则一直阻塞。无法执行
ExecutorService threadPool = new ThreadPoolExecutor(3, 20, 2000L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1024), threadFactory, new ThreadPoolExecutor.AbortPolicy());
执行结果
当前线程名:demo-pool-0 当前线程名:demo-pool-1 当前线程名:demo-pool-2 主线程程序执行
Cyclicbarrier和Countdownlatch的区别
|CountDownLatch|CyclicBarrier|| -- | -- |
| 减基数方式 | 加基数方式 |
| 计数为0的时候释放所有等待的线程 | 基数达到指定值时释放所有等待线程 |
| 基数为0时,无法重置,只能使用一次 | 基数达到指定值时,计数置为0,重新开始 |
| 调用countDown方法减一,await方法阻塞 | 调用await方法 |
| 不可重复使用 | 可重复使用 |
相关文章推荐
- Java CountDownLatch 和 CyclicBarrier 使用
- java并发编程中CountDownLatch和CyclicBarrier的使用
- Java多线程之CountDownLatch和CyclicBarrier同步屏障的使用
- Concurrent常用工具类的使用(CyclicBarrier/CountDownLatch/Callable)
- 多线程并发常用类:condition,semaphore,CyclicBarrier,countdownlatch,exchanger使用整理
- Java并发编程中CountDownLatch和CyclicBarrier的使用
- 线程池的创建以及CyclicBarrier与CountDownLatch的简单使用
- CountDownLatch的和CyclicBarrier使用
- CyclicBarrier及CountDownLatch的使用
- Java并发编程中CountDownLatch和CyclicBarrier的使用
- 【Java多线程】CountDownLatch、CyclicBarrier和Semaphore使用
- java并发编程中CountDownLatch和CyclicBarrier的使用 - [java]
- java.util.concurrent 下的Semaphore CyclicBarrier CountDownLatch 分析使用
- Java线程计数器CyclicBarrier和CountDownLatch的使用
- 线程池的创建以及CyclicBarrier与CountDownLatch的简单使用
- jdk的CountdownLatch和CyclicBarrier的使用
- CountDownLatch,CyclicBarrier,Semaphore的使用
- Java中的并发工具CountDownLatch、CyclicBarrier、Semapphore使用详解
- java并发编程中CountDownLatch和CyclicBarrier的使用
- Java并发编程中CountDownLatch和CyclicBarrier的使用