【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
其实两者的用法异曲同工
先说说CyclicBarrier,看看初始化:
有两种初始化,其实很容易理解,第一个是说多少个parties需要执行(通过调用CyclicBarrier.await()来计算线程数量),执行完成后BarrierAction最后收尾执行,第二个就是说多少个线程需要执行(通过调用CyclicBarrier.await()来计算线程数量),执行完成后不需要收尾。
功能:有多少个线程执行完之后所有线程才能一起执行下一个。
特性:使用AQS和CAS确保线程安全,调用await()会进入condition queue,然后等所有线程执行完成后,也就是count增加到指定值,然后会调用signalAll()将条件队列中的移入到sync queue去执行。
再说说CountDownLatch,初始化:
声明一个数字,然后调用自己的await方法,等待其他线程通过调用countDown方法将此数字减到0,然后唤醒当前的线程。
功能:当前线程等待其他线程执行完之后再执行。
特性:使用CAS和AQS保证线程安全
区别:
1.cyclicBarrier使用加法到一定数目后唤醒所有线程,countDownLatch使用减法到0时唤醒主线程。
2.cyclicBarrier可以循环使用,可以通过reset方法去重置,countDownLatch是一次性的执行完就结束。
3.cyclicBarrier是让一堆线程等待然后一起再执行。countDownLatch是一个线程等待其他线程结束完成。
样例:
countDownLatch:
往集合里加是个元素,加个第五个的时候提示一下。
public static void main(String[] args) { CountDownLatch countDownLatch = new CountDownLatch(1); ConcurrentLinkedQueue clq = new ConcurrentLinkedQueue(); B b = new B(countDownLatch); new Thread(b).start(); A a = new A(countDownLatch, clq); new Thread(a).start(); }
static class A implements Runnable { CountDownLatch cdl ; ConcurrentLinkedQueue clq ; public A(CountDownLatch countDownLatch,ConcurrentLinkedQueue clq) { this.cdl = countDownLatch; this.clq = clq; } @Override public void run() { for(int i=0;i<9;i++) { clq.add("1"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("添加第" + i + "个"); if (clq.size() == 5) { cdl.countDown(); } } } } static class B implements Runnable { CountDownLatch cdl ; public B( CountDownLatch cdl ){ this.cdl = cdl; } @Override public void run() { try { cdl.await(); System.out.println("已经5个了"); } catch (InterruptedException e) { e.printStackTrace(); } } }
cyclicBarrier:
计算十名员工的工资,形成表格汇总,通知员工领工资,然后员工再领工资。
public static void main(String[] args) throws BrokenBarrierException, InterruptedException { ConcurrentHashMap concurrentHashMap = new ConcurrentHashMap<String, Integer>(); AtomicInteger a = new AtomicInteger(); CyclicBarrier cyclicBarrier = new CyclicBarrier(10, new Runnable() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } int size = concurrentHashMap.entrySet().size(); System.out.println("所有线程计算完成,共" + size + "名,结果如下:"); Iterator iterator = concurrentHashMap.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, Integer> en = (Map.Entry<String, Integer>) iterator.next(); System.out.println(en.getKey() + ":" + en.getValue()); } } }); ThreadLocal<Integer> ad = new ThreadLocal<Integer>(); ExecutorService exSer = newCachedThreadPool(); // A aa = new A(); ThreadLocal<A> aa = new ThreadLocal<A>(); for (int i = 0; i < 9; i++) { exSer.submit(new Runnable() { @Override public void run() { // ad.set(a.incrementAndGet()); aa.set(new A(a.incrementAndGet())); concurrentHashMap.put("员工" + (aa.get().getA()), Math.random() * 10000); System.out.println(Thread.currentThread().getName() + "计算完成员工" + (aa.get().getA()) + "的工资"); try { cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } System.out.println("通知员工" + aa.get().getA() + "领工资啦"); try { //等待是为了让reset生效 Thread.currentThread().sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("睡醒"); try { cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } exSer.submit(new Remove("员工" + aa.get().getA(), concurrentHashMap)); } }); } cyclicBarrier.await(); System.out.println("cyclicBarrier.isBroken()---" + cyclicBarrier.isBroken()); cyclicBarrier.reset(); System.out.println("cyclicBarrier.isBroken()---" + cyclicBarrier.isBroken()); cyclicBarrier.await(); // exSer.shutdown(); } static class A { public A(int a) { this.a = a; } int a; public int getA() { return a; } public void setA(int a) { this.a = a; } } static class Remove implements Runnable { String name; ConcurrentHashMap con; public Remove(String name, ConcurrentHashMap con) { this.name = name; this.con = con; } @Override public void run() { con.remove(name); System.out.println(name + "领取了工资"); } }
运行结果:
pool-1-thread-6计算完成员工6的工资
pool-1-thread-8计算完成员工3的工资
pool-1-thread-2计算完成员工9的工资
pool-1-thread-1计算完成员工1的工资
pool-1-thread-7计算完成员工4的工资
pool-1-thread-5计算完成员工5的工资
pool-1-thread-3计算完成员工8的工资
pool-1-thread-4计算完成员工7的工资
pool-1-thread-9计算完成员工2的工资
所有线程计算完成,共9名,结果如下:
员工4:2342.2147453667794
员工3:2067.969946452305
员工2:4868.520645427759
员工1:5147.003352118165
员工9:3955.4686122160765
员工8:2043.424792081039
员工7:7147.287327017816
员工6:1023.2789412425269
员工5:1437.6584893765355
通知员工2领工资啦
通知员工6领工资啦
通知员工1领工资啦
通知员工5领工资啦
通知员工9领工资啦
通知员工3领工资啦
cyclicBarrier.isBroken()---false
通知员工7领工资啦
通知员工8领工资啦
通知员工4领工资啦
cyclicBarrier.isBroken()---false
来源:oschina
链接:https://my.oschina.net/u/4291478/blog/3151240