Synchronizer
控制多个线程的流程,比如线程执行到某一个点的时候是等待还是通过。 JDK中自带了信号量,关卡,闭锁
闭锁CoutDownLatch
达到最终状态前是关闭的,所有线程在此阻塞, 达到最终状态后开放,并且不可以再修改,所有线程进入可运行状态。
很适合,等待初始化, 等待依赖等等场景。
如:
/** * 设置countDownLatch的初始值, * 用await()来等待 * 用countDown来倒计时 --初始值 * 当初始值为0时await()等待被notify */ public class TestLatch { public static void main(String[] args) { final CountDownLatch latch = new CountDownLatch(1); final String[] datas = new String[3]; new Thread(){ @Override public void run() { try { System.out.println("等待初始化"); latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("初始化完成。开始执行"); for (String data : datas) { System.out.println(data); } } }.start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } datas[0] = "我"; datas[1] = "爱"; datas[2] = "你"; System.out.println("初始化完成"); latch.countDown(); } }
信号量
适用于连接池等场景
/** * 创建一个含有固定许可数的信号量 * 线程用acquire()标记获得了一个许可,切许可-1,当许可为0时等待, * 用release来释放许可,许可+1,其他等待的线程可以获得许可了。 */ public class TestSemaphore { public static void main(String[] args) { final Semaphore semaphore = new Semaphore(5); for (int i = 0; i < 20; i++) { new Thread("thread" + i){ @Override public void run() { try { semaphore.acquire(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(getName() + "正在执行"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } semaphore.release();; } }.start(); } } }
关卡
与闭锁不同的是,闭锁等待状态,而关卡是等待线程。
特别适用于把一个计算拆分成多个进行计算,最后再进行整合。
/** * 关卡 * 定义所有线程都到关卡之后的行为及关卡中包含的线程数量 * * 各个线程使用await方法来表示已经到这个关卡等着了 * * 当指定数目的线程等着了,那么就开放关卡, 所有线程及刚才定义的行为都继续执行 */ public class TestBarrier { public static void main(String[] args) { final String[] friends = new String[]{"1", "2", "3"}; final CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new Runnable() { @Override public void run() { System.out.println("出发"); } }); for (final String friend : friends) { new Thread(){ @Override public void run() { System.out.println(friend + "到集合点了"); try { cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } System.out.println(friend + "出发"); } }.start(); } } }
打印如下:
1到集合点了 3到集合点了 2到集合点了 出发 2出发 3出发 1出发