• Java并发编程的艺术笔记-Java中的并发工具类


    1.CountDownLatch

    • CountDownLatch允许一个或多个线程等待其他线程完成操作

    • join方法:

      • join用于让当前执行线程等待join线程执行结束,原理是不停检查join线程是否存活,如果join线程存活则让当前线程永远等待
      while (isAlive()) {
          wait(0);
      }
      
      • 1
      • 2
      • 3
      • 待join线程中止后,线程的this.notifyAll()方法会被调用(该方法是在JVM里实现的,JDK里看不到)
    • CountDownLatch的使用:

    static CountDownLatch c = new CountDownLatch(2);  // 设置计数器的值为2
    public static void main(String[] args) throws InterruptedException {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(1);
                c.countDown();  // 计数器减1
                System.out.println(2);
                c.countDown();  // 计数器减1
            }
        }).start();
        c.await();  // 阻塞主线程,直到计数器的值为0
        System.out.println("3");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2.CyclicBarrier

    • 让一组线程到达一个屏障(也叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行(所有线程等待完成,然后一起做事情)

    • 每个线程调用await方法告诉CyclicBarrier我已经到达了屏障,然后当前线程被阻塞

    static CyclicBarrier c = new CyclicBarrier(2);
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    ---业务代码-----
                    // 插入一个屏障
                    c.await();  // 等另一个线程准备好再继续往下执行
                } catch (Exception e) {
                }
                System.out.println(1);
            }
        }).start();
        try {
            ---业务代码-----
            // 插入一个屏障
            c.await();  // 等另一个线程准备好再继续往下执行(这里是主线程等待另一个线程)
        } catch (Exception e) {
        }
        System.out.println(2);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • CyclicBarrier(int parties,Runnable barrierAction)用于在线程到达屏障时,优先执行barrierAction,方便处理更复杂的业务场景:
    // 等代码中的第一个线程和线程A都执行完之后,才会继续执行主线程(输出3 1 2)
    static CyclicBarrier c = new CyclicBarrier(2, new A());
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    c.await();  // 插入一个屏障
                } catch (Exception e) {
                }
                System.out.println(1);
            }
        }).start();
        try {
            c.await();  // 插入一个屏障
        } catch (Exception e) {
        }
        System.out.println(2);
    }
    
    static class A implements Runnable {
        @Override
        public void run() {
            System.out.println(3);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • CyclicBarrier和CountDownLatch的区别:
      • CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以使用reset()方法重置(所以能处理更为复杂的业务场景)
      • CountDownLatch是一/多个线程(老师)等待另外N个线程完成某个事情之后才能执行(N个学生做完了试卷就可走,不用等待其他的学生完成);CyclicBarrier是N个线程相互等待,任何一个线程完成之前,所有的线程都必须等待(一个游戏玩家加载到100%还不可以开局,须要等到其他N-1的游戏玩家都加载到100%才可以开局)

    3.Semaphore

    • Semaphore(信号量)用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源

    • 用于做流量控制,特别是公用资源有限的应用场景

    private static final int THREAD_COUNT = 30;
    private static ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_COUNT);
    private static Semaphore s = new Semaphore(10);
    public static void main(String[] args) {
        // 虽然有30个线程在执行,但是只允许10个并发执行
        for (int i = 0; i< THREAD_COUNT; i++) {
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        s.acquire();  // 获取许可证
                        System.out.println("save data");
                        s.release();  // 归还许可证
                    } catch (InterruptedException e) {
                    }
                }
            });
        }
        threadPool.shutdown();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    4.Exchanger

    • Exchanger(交换者)是用于线程间协作的工具类(进行线程间的数据交换)

    • 提供一个同步点,在这个同步点中两个线程可以交换彼此的数据

    • 如果第一个线程先执行exchange方法,它会一直等待第二个线程也执行exchange方法,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方

    private static final Exchanger<String> exgr = new Exchanger<>();
    private static ExecutorService threadPool = Executors.newFixedThreadPool(2);
    
    public static void main(String[] args) {
        threadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    String A = "银行流水1";  // A录入银行流水数据
                    exgr.exchange(A);  // A表示需要和另个线程传递的数据
                } catch (InterruptedException e) {
                }
            }
        });
        threadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    String B = "银行流水2";  // B录入银行流水数据
                    String A = exgr.exchange(B);  // B表示需要和另个线程传递的数据,A表示从另个线程提供的数据
                    System.out.println("A和B数据是否一致:" + A.equals(B) + ",A录入的是:" + A + ",B录入是:" + B);
                } catch (InterruptedException e) {
                }
            }
        });
        threadPool.shutdown();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

  • 相关阅读:
    GDB调试-链接器
    文件、异常、模块
    MYSQL索引详解和优化
    Qt setStyleSheet Selector不生效
    golang template 使用
    速锐得解码匹配驾培驾考吉利几何E萤火虫数据应用智能评判系统
    Starfish Os打造娱乐化元宇宙商业生态
    使用Docker安装MySQL5.7.36
    JDK8新特性超详细总结
    ORA-00600 【3948】,ORA-00600 【3949】
  • 原文地址:https://blog.csdn.net/qq_41398418/article/details/126259783