CountDownLatch
每次当线程调用countDownLatch.countDown()方法时,会对计数器减1,减到0,countDownLatch.await()放行
public class CountDownLatchTest { public static void main(String[] args) { CountDownLatch count = new CountDownLatch(7); for (int i=0; i < 7; i++){ final int tempInt = i; new Thread(()->{ System.out.println("线程"+tempInt+"执行"); count.countDown(); },String.valueOf(i)).start(); } try { count.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("主线程开始执行"); } }
CyclicBarrier
与上面相反,当await()累计达到n次时,执行runnable 接口的线程。
public class CyclicBarrierTest { public static void main(String[] args) { CyclicBarrier cyc = new CyclicBarrier(7,()->{ System.out.println("一切就绪"); }); for (int i=0; i < 7; i++){ final int tempInt = i; new Thread(()->{ System.out.println("线程"+tempInt+"执行"); try { cyc.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } },String.valueOf(i)).start(); } } }
Semaphore
public class SemaphoreTest { public static void main(String[] args) { // 只有三个车位 Semaphore semaphore = new Semaphore(3); for (int i=0; i < 6; i++){ new Thread(()->{ try { // 表示占到车位 semaphore.acquire(); System.out.println(Thread.currentThread().getName()+"正在占用车位"); // 停三秒 try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } // 离开 System.out.println("离开车位"); } catch (InterruptedException e) { e.printStackTrace(); } finally { // 释放车位 semaphore.release(); } },String.valueOf(i)).start(); } } }
三者区别
CountDownLatch
创建一个所有线程共享的对象count(具有初始值n),
任意线程中调用countDown()方法会使n的数值减少1。
n减少到零后,对象的await()方法才会被唤醒
CyclicBarrier
创建的cyclicBarrier对象自带一个Runnable对象,以及一个最大域值n。
当线程中的对象每调用一次await()方法,基础阈值加一(从0开始),直到阈值达到n时,会调用Runnable对象的方法。
SemaPhore
创建对象后会分配一个大小为n的区域
线程中使用对象的acquire()方法得到分配。如果无法得到则会阻塞。直到其他区域被释放(调用release()方法)