1.CountDownLatch
await(),进入等待的状态
countDown(),计数器减一 应用场景:启动三个线程计算,需要对结果进行累加。/** * * CountDownLatch Demo * */public class CountDownLatchDemo { public static void main(String[] args) { CountDownLatch countDownLatch = new CountDownLatch(8); new Thread(()->{ try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("800米比赛结束,准备清空跑道并继续跨栏比赛"); }).start(); for (int i = 0; i < 8; i++) { final int finalI = i;// System.out.println("fin->"+finalI); new Thread(()->{ try { Thread.sleep(finalI * 1000L); System.out.println(Thread.currentThread().getName()+"到达终点了"); } catch (InterruptedException e) { e.printStackTrace(); }finally { countDownLatch.countDown(); } }).start(); } }}
2.CyclicBarrier--栅栏
允许一组线程相互等待达到一个公共的障碍点,之后再继续执行
跟countDownLatch的区别 CountDownLatch一般用于某个线程等待若干个其他线程执行完任务之后,它才执行;不可重复使用 CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行;可重用的/** * 栅栏系统 */public class CyclicBarrierDemo { public static void main(String[] args) { CyclicBarrier cyclicBarrier = new CyclicBarrier(8); for (int i = 0; i < 8; i++) { int finalI = i; new Thread(()->{ try { Thread.sleep(finalI *1000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"准备就绪"); try { cyclicBarrier.await(); } catch (Exception e) { e.printStackTrace(); } System.out.println("开始比赛"); }).start(); } }}
3.Semaphore--信号量
控制并发数量
使用场景:接口限流/** * Semaphore * 控制进来的最多的线程数量 等释放后才允许后续的进来 */public class SemaphoreDemo { public static void main(String[] args) { Semaphore semaphore = new Semaphore(8); for (int i = 0; i < 10; i++) { new Thread(()->{ try { semaphore.acquire(); System.out.println(Thread.currentThread().getName()+"开始执行"); Thread.sleep(5000L); } catch (InterruptedException e) { e.printStackTrace(); }finally { //最后需要释放 semaphore.release(); } }).start(); } }}
4.Exchanger
用于交换数据
它提供一个同步点,在这个同步点两个线程可以交换彼此的数据。这两个线程通过exchange方法交换数据, 如果第一个线程先执行exchange方法,它会一直等待第二个线程也执行exchange,当两个线程都到达同步点 时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方。因此使用Exchanger的重点是成对的 线程使用exchange()方法,当有一对线程达到了同步点,就会进行交换数据。因此该工具类的线程对象是【成 对】的。/** * Exchanger 线程间的数据交换 * 交换线程数量必须成对 * */public class ExchangerDemo { public static void main(String[] args) { ExchangerstringExchanger = new Exchanger<>(); String str1 = "str001"; String str2 = "str002"; new Thread(()->{ System.out.println(Thread.currentThread().getName() +"初始化的数据==>"+str1 ); try { //开始交换数据 String exchange = stringExchanger.exchange(str1); System.out.println(Thread.currentThread().getName() +"交换后的数据==>"+exchange ); } catch (InterruptedException e) { e.printStackTrace(); } },"线程1").start(); new Thread(()->{ System.out.println(Thread.currentThread().getName() +"初始化的数据==>"+str2 ); try { //开始交换数据 String exchange = stringExchanger.exchange(str2); System.out.println(Thread.currentThread().getName() +"交换后的数据==>"+exchange ); } catch (InterruptedException e) { e.printStackTrace(); } },"线程2").start(); }}