1. 倒计时锁存器

CountDownLatch :允许一个或多个线程等待其它线程完成操作。
使用举例:

  1. private static CountDownLatch c = new CountDownLatch(3);
  2. public static void main(String[] args) throws InterruptedException{
  3. for(int i=0; i<3; i++){
  4. final int id = i;
  5. new Thread(() -> {
  6. try{
  7. Thread.sleep(2000*id);
  8. c.countDown(); // 一个任务完成
  9. System.out.println(id + " Done");
  10. } catch (InterruptedException ignore){}
  11. }).start();
  12. }
  13. c.await(); // 等待所有任务完成
  14. System.out.println("All Done");
  15. }

2. 同步屏障

CyclicBarrier :一组中的若干个线程到达某一个同步点时被阻塞,直到所有线程都完成才让这些线程继续运行。

  1. private static CyclicBarrier c = new CyclicBarrier(3); // 通过屏障所需要的线程数
  2. public static void main(String[] args) throws InterruptedException{
  3. for(int i=0; i<3; i++){
  4. final int id = i;
  5. new Thread(() -> {
  6. try{
  7. Thread.sleep(2000*id);
  8. System.out.println(id + " Done");
  9. c.await(); // 到达同步点
  10. System.out.println(id + " Pass");
  11. } catch (InterruptedException | BrokenBarrierException ignore){}
  12. }).start();
  13. }
  14. }

提供一个高级方式: CyclicBarrier(int parties, Runnable barrierAction) ,突破屏障时会优先执行barrierAction

CountDownLatch 的区别:

  • 倒计时锁存器的计数器只能使用一次,而同步屏障的计数器可以用 reset() 重置。

    3. 信号量

    Semaphore 用来控制同时访问某特定资源的线程数量,常用来做流量控制。

  • acquire() :获取信号资源,如果无法获取将阻塞。

  • release() : 释放信号资源。

    4. 线程信号交换

    Exchanger :用于线程间协作,如数据交换。两个线程间通过 exchange() 等待交换数据,先执行的线程会等待后者,在同步点交换数据。
    使用示例: ```java private static Exchanger e = 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*/

  1. <a name="y3G0O"></a>
  2. ## 5.线程阻塞工具类
  3. `LockSupport` 工具类用于阻塞或唤醒一个线程。阻塞: `part()` 、 `parkNanos(long)` 、 `parkUntil(long)` ;唤醒: `unpark(Thread)` 。<br />使用示例:
  4. ```java
  5. public class test { // 样例:多线程无限按序打印1~n的数字
  6. private static int n = 10;
  7. private static LinkedList<Thread> list = new LinkedList<>();
  8. public static void main(String[] args){
  9. for(int i=0; i<n; i++){
  10. Thread crn = new Thread(new R(i));
  11. list.add(crn);
  12. crn.start();
  13. }
  14. LockSupport.unpark(list.get(0));
  15. }
  16. static class R implements Runnable{
  17. private int id;
  18. R(int id){this.id = id;}
  19. @Override
  20. public void run(){
  21. while (true){
  22. LockSupport.park();
  23. System.out.println(this.id);
  24. LockSupport.unpark(list.get((this.id+ 1) % n)); // 唤醒下一个线程
  25. }
  26. }
  27. }
  28. }