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 />使用示例:
```java
public 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;}
@Override
public void run(){
while (true){
LockSupport.park();
System.out.println(this.id);
LockSupport.unpark(list.get((this.id+ 1) % n)); // 唤醒下一个线程
}
}
}
}