一个同步工具,使得一个或多个线程等待一组线程执行完成后再执行。dom
使用场景:等待一些前置任务执行完成后,再执行特定的功能。好比,系统启动时,各类配置生效后,才能运行提供服务。ide
public class CountDownLatchTest { public static void main(String[] args) { final CountDownLatch latch = new CountDownLatch(5); for (int i = 0; i < 5; i++) { new Thread(new Runnable() { @Override public void run() { try { TimeUnit.SECONDS.sleep(new Random().nextInt(10)); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " end, " + System.currentTimeMillis()); latch.countDown(); } }).start(); } try { System.out.println("main latch.await() " + System.currentTimeMillis()); latch.await(); System.out.println("main latch.await() end " + System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } } }
特别注意:CountDownLatch初始化时,数量必定要等于等待的线程的数量。工具
CyclicBarrier(可循环同步屏障),控制一组线程相互等待,直到全部线程都到达屏障点。全部线程都到达屏障点后,同时开始执行剩余的任务。ui
可循环,意味着当全部线程都到达屏障后,屏障能够被再次重复利用。线程
多个任务同时到达某个临界状况时,才能同时执行剩余任务,不然相互等待。code
public class CyclicBarrierTest { public static void main(String[] args) { int num = 3; final CyclicBarrier barrier = new CyclicBarrier(num); for (int i = 0; i < num; i++) { new Thread(new Runnable() { @Override public void run() { try { TimeUnit.SECONDS.sleep(new Random().nextInt(5)); System.out.println(Thread.currentThread().getName() + "执行结束,开始等待其它线程, " + System.currentTimeMillis()); barrier.await(); System.out.println(Thread.currentThread().getName() + "全部线程等待都执行完成,开始执行剩下任务, " + System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } }).start(); } // 屏障能够在上一次使用完成后被再次使用 for (int i = 0; i < num; i++) { new Thread(new Runnable() { @Override public void run() { try { TimeUnit.SECONDS.sleep(new Random().nextInt(5)); System.out.println(Thread.currentThread().getName() + "执行结束,开始等待其它线程, " + System.currentTimeMillis()); barrier.await(); System.out.println(Thread.currentThread().getName() + "全部线程等待都执行完成,开始执行剩下任务, " + System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } }).start(); } System.out.println("main end at " + System.currentTimeMillis()); } }
Semaphore(信号量),一个计数信号量。概念上,一个信号量维持了一个许可集合。对象
实际上,并无真正的许可对象,只是计数。资源
限制资源同时被访问的线程数量get
public class SemaphoreTest { public static void main(String[] args) { final Semaphore semaphore = new Semaphore(3); for (int i = 0; i < 10; i++) { new Thread(new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread().getName() + "尝试获取许可, " + System.currentTimeMillis()); semaphore.acquire(); System.out.println(Thread.currentThread().getName() + "获取许可, " + System.currentTimeMillis()); TimeUnit.SECONDS.sleep(new Random().nextInt(5)); System.out.println(Thread.currentThread().getName() + "执行结束, " + System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); } } }).start(); } System.out.println("main end! " + System.currentTimeMillis()); } }
特别注意:得到许可并执行完逻辑后,必定要释放,不然许可不会被归还。(有借有还,再借不难)同步