该类主要实现了:让一个线程等待其余线程完成后再执行的功能,比如Thread.join()
。java
该类的初始化须要一个整数值count,当每次调用CountDownLatch.countDown()
时Count会递减。直到count降到0时,全部执行CountDownLatch.await()
的方法都会返回。算法
初始化了一个共享变量latch,并赋予count为3数据库
CountDownLatch latch = new CountDownLatch(3);
建立一个任务,睡眠1秒伪装执行任务,最后执行countDownide
@Override public void run() throw InterruptedException{ System.out.println("执行任务..."); Thread.sleep(1000); latch.countDown(); }
主线程里执行以下方法工具
// 调用3个线程执行上述的任务 ... latch.await(); System.out.println("执行结束")
当三个任务线程所有执行完latch.countDown()时,main线程就会从阻塞的await()中返回,最后输出"执行结束"。
注意:CountDownLatch 只能使用一次,下一次使用要从新建立一个。学习
该类和CountDownLatch有点相似,不过从名字就能够看出它是一个可循环使用 的类。它的功能主要是等待全部线程达到某个位置,而后统一执行。能够想象成出发旅游,你们都先到集合地等待,待全部人都到了,就能够出发了。线程
建立一个屏障code
CyclicBarrier barrier = new CyclicBarrier(4);
任务类,让先完成的任务进行等待,等待其余线程到达get
@Override public void run() throw InterruptedException{ System.out.println(Thread.currentThread.getName() + " -> 到达集合点"); barrier.await(); System.out.println(Thread.currentThread.getName() + "出发!") }
睡5秒,不让主线程过早结束同步
// 建立4个线程执行上述的任务 ... Thread.sleep(5000); System.out.println("执行结束")
注意,若是barrier在等待过程当中某个线程被中断了一次,那么整个barrier就须要从新来过。
Thread thread = new Thread(() -> { try { barrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }); thread.start(); thread.interrupt(); try{ barrier.await(); }catch (Exception e){ System.out.println("没法等待..."); }
当另起的线程被中断后,后续的barrier就没法使用了,会抛出BrokenBarrierException
该类被称做信号量,用于控制同一时间的线程执行数。想象下面一副场景:
----------------- 🚌 🚌 🚌 🚌↘--------------- 🚌 🚌 🚌 🚌🚌 🚌🚌 🚌 🚌 🚌↗--------------- -----------------
在窄路口里每次只能经过5辆车,5辆车经过后,后5辆车才能经过。Semaphore的做用就和它很相似,当有20条线程在执行IO密集型的任务,执行完后须要将处理结果存储到数据库中。若是数据库链接只有10条,那就要用semaphore去控制拿到数据库链接的线程数量。
Semaphore里没用过的方法:
该类是一个用于线程间协做的工具类。Exchanger用于进行线程间的数据交换。它提供一个同步点,在这个通不见,两个线程能够交换彼此间的数据。这两个线程经过exchange方法交换数据:若是第一个线程执行exchange(),它会一直等待第二个线程exchange(),当两个线程达到同步点,这两个线程就能够交换线程。
虽然我不知道这个类有啥做用(ε=ε=ε=┏(゜ロ゜;)┛
可是书上说能够用于遗传算法、校对工做:
Exchanger<String> exchanger = new Exchanger<>(); new Thread(() -> { String dataOfAThread = Thread.currentThread().getName() + "-----A的数据"; try { String resultOfBThread = exchanger.exchange(dataOfAThread); System.out.println(Thread.currentThread().getName() + "-------> " + resultOfBThread); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); new Thread(() -> { String dataOfBThread = Thread.currentThread().getName() + "-----B的数据"; try { String resultOfAThread = exchanger.exchange(dataOfBThread); System.out.println(Thread.currentThread().getName() + "-------> " + resultOfAThread); } catch (InterruptedException e) { e.printStackTrace(); } }).start();
最后输出:
Thread-1-------> Thread-0-----A的数据 Thread-0-------> Thread-1-----B的数据
从新熟悉一下同步工具,学习到了CyclicBarrier被中断一次后,整个做废的点;学习到了Exchanger的适用场景