• 线程基础知识16线程相关类CyclicBarrier、Semaphore、Exchanger


    1 CyclicBarrier

    1.1 作用

      从字面上的意思可以知道,这个类的中文意思是“循环栅栏”。大概的意思就是一个可循环利用的屏障。

      它的作用就是会让所有线程都等待完成后才会继续下一步行动

    1.2 示例

    //等待指定数量的线程await之后,执行一个runnable。并且await的线程继续执行await后面的代码。
        // 如果达不到这个数量,会一直阻塞
        private static void m1() {
            CyclicBarrier c = new CyclicBarrier(5,()->System.out.println(Thread.currentThread().getName()+"发车"));
            for (int i = 0;i < 22;i++){
                new Thread(()->{
                    try { c.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); }
                    System.out.println(Thread.currentThread().getName());
                    },"线程" + i).start();
            }
    
            System.out.println("aaa");
        }

    1.3 执行结果

      上面代码创建一个CyclicBarrier ,设定的是5个线程到达后,才可以执行创建CyclicBarrier 传入的runnable,然后5个线程继续执行

      由于是每5个线程才能一期继续执行,而循环共创建22个线程,所以会有两个线程一直阻塞无法向下执行

    线程6发车
    线程6
    线程4发车
    线程4
    aaa
    线程0
    线程1
    线程2
    线程17发车
    线程3
    线程10
    线程9
    线程5
    线程20
    线程7
    线程16
    线程8
    线程17
    线程12
    线程15发车
    线程15
    线程18
    线程19
    线程21
    线程14

    2 Semaphore

    2.1 作用

    限制同时执行的线程数(限流)

    2.2 示例

    private static void m3() {
            Semaphore sp = new Semaphore(3);//允许最多三个线程同时请求执行
    
            for (int i = 0;i < 20;i++){
                new Thread(()->{
                    try {
                        sp.acquire();  //请求执行
                        System.out.println(Thread.currentThread().getName());
                        Thread.sleep(100);
                        System.out.println(Thread.currentThread().getName() + "继续执行");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        sp.release(); //释放
                    }
                },"线程" + i).start();
            }
        }

    2.3 执行结果

      发现同时执行的线程最多3个

    线程0
    线程2
    线程1
    线程1继续执行
    线程0继续执行
    线程2继续执行
    线程3
    线程4
    线程5
    线程5继续执行
    线程3继续执行
    线程4继续执行
    线程7
    线程6
    线程9
    线程6继续执行
    线程7继续执行
    线程9继续执行
    线程10
    线程8
    线程11
    线程11继续执行
    线程10继续执行
    线程8继续执行
    线程13
    线程12
    线程14
    线程12继续执行
    线程14继续执行
    线程13继续执行
    线程16
    线程15
    线程17
    线程16继续执行
    线程17继续执行
    线程15继续执行
    线程18
    线程19
    线程19继续执行
    线程18继续执行

    3 Exchanger

    3.1 作用

    用于两个线程交换数据

    3.2 示例

    private static void m4() {
            Exchanger<String> ex = new Exchanger();  //用于两个线程交换数据
    
            new Thread(()->{
                try {
                    String exchange = ex.exchange("111"); //调用exchange时会阻塞,等待另一个线程调用exchange方法,交换数据后,两个线程继续执行
                    System.out.println(Thread.currentThread().getName() + ":" + exchange);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
            },"线程1").start();
    
            new Thread(()->{
                try {
                    Thread.sleep(1000);
                    String exchange = ex.exchange("222");
                    System.out.println(Thread.currentThread().getName() + ":" + exchange);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
            },"线程2").start();
        }

    3.3 执行结果

      发现两个线程交换了数据,且调用exchange方法会导致阻塞,直到另一个线程也调用exchange方法,完成数据交换,线程才能继续执行

    线程1:222
    线程2:111
  • 相关阅读:
    Spring.profile配合Jenkins发布War包,实现开发、测试和生产环境的按需切换
    Ubuntu 配置 Tomcat
    Proper usage of Java -D command-line parameters
    Linux下设置MySql自动启动
    cent6.x配置主机名及静态网络
    vmware can not be closed virtual machine is busy
    VMware虚拟机下扩容磁盘(centos7)
    Spring、MyBatis、Shiro、Quartz、Activiti框架
    Jenkins ChangeLog
    JEECG DataGridColumn dictionary使用问题
  • 原文地址:https://www.cnblogs.com/jthr/p/16673063.html
Copyright © 2020-2023  润新知