1. 倒计时锁存器
CountDownLatch :允许一个或多个线程等待其它线程完成操作。
使用举例:
private static CountDownLatch c = new CountDownLatch(3);public static void main(String[] args) throws InterruptedException{for(int i=0; i<3; i++){final int id = i;new Thread(() -> {try{Thread.sleep(2000*id);c.countDown(); // 一个任务完成System.out.println(id + " Done");} catch (InterruptedException ignore){}}).start();}c.await(); // 等待所有任务完成System.out.println("All Done");}
2. 同步屏障
CyclicBarrier :一组中的若干个线程到达某一个同步点时被阻塞,直到所有线程都完成才让这些线程继续运行。
private static CyclicBarrier c = new CyclicBarrier(3); // 通过屏障所需要的线程数public static void main(String[] args) throws InterruptedException{for(int i=0; i<3; i++){final int id = i;new Thread(() -> {try{Thread.sleep(2000*id);System.out.println(id + " Done");c.await(); // 到达同步点System.out.println(id + " Pass");} catch (InterruptedException | BrokenBarrierException ignore){}}).start();}}
提供一个高级方式: CyclicBarrier(int parties, Runnable barrierAction) ,突破屏障时会优先执行barrierAction。
与 CountDownLatch 的区别:
倒计时锁存器的计数器只能使用一次,而同步屏障的计数器可以用
reset()重置。3. 信号量
Semaphore用来控制同时访问某特定资源的线程数量,常用来做流量控制。acquire():获取信号资源,如果无法获取将阻塞。release(): 释放信号资源。4. 线程信号交换
Exchanger:用于线程间协作,如数据交换。两个线程间通过exchange()等待交换数据,先执行的线程会等待后者,在同步点交换数据。
使用示例: ```java private static Exchangere = new Exchanger ();
public static void main(String[] args) throws InterruptedException{ for(int i=0; i<2; i++){ final int id = i; new Thread(() -> { try{ Thread.sleep(2000id); System.out.println(id + “ done, send msg:” + id); int rec = e.exchange(id); // 交换数据的同步点 System.out.println(id + “ Pass, recevie “+ rec); } catch (InterruptedException ignore){} }).start(); } }/ print: 0 done, send msg:0 1 done, send msg:1 0 Pass, recevie 1 1 Pass, recevie 0*/
<a name="y3G0O"></a>## 5.线程阻塞工具类`LockSupport` 工具类用于阻塞或唤醒一个线程。阻塞: `part()` 、 `parkNanos(long)` 、 `parkUntil(long)` ;唤醒: `unpark(Thread)` 。<br />使用示例:```javapublic class test { // 样例:多线程无限按序打印1~n的数字private static int n = 10;private static LinkedList<Thread> list = new LinkedList<>();public static void main(String[] args){for(int i=0; i<n; i++){Thread crn = new Thread(new R(i));list.add(crn);crn.start();}LockSupport.unpark(list.get(0));}static class R implements Runnable{private int id;R(int id){this.id = id;}@Overridepublic void run(){while (true){LockSupport.park();System.out.println(this.id);LockSupport.unpark(list.get((this.id+ 1) % n)); // 唤醒下一个线程}}}}
