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