zoukankan      html  css  js  c++  java
  • JUC常用的4种工具、CountDownLatch、CyclicBarrier、Semaphore、Exchanger、常用方法

    JUC常用工具(组件)类 JDK 1.5

    都实现了AQS类

    1、CountDownLatch

    java.util.concurrent.CountDownLatch 类,是一个减计数器

    构造方法

    • public CountDownLatch(int count) 设置计数的总数

    常用方法

    • public void await() throws InterruptedException 等待计数为0,计数为0,才可以执行之后的代码

    • public boolean await(long timeout,TimeUnit unit) throws InterruptedException

      timeout:等待时间

      unit:timeout参数的时间单位

      返回结果:true计数为0;false到达了时间且计数还没有为0

    • public void countDown() 计数减1

    • public long getCount() 返回当前计数

    public class CountDownLatchTest {
        public static void main(String[] args) throws InterruptedException {
            CountDownLatch countDownLatch = new CountDownLatch(6); // 设置总数为6
    
            for (int i = 1; i <= 6; i++) {
                new Thread(()->{
                    countDownLatch.countDown(); // -1
                    System.out.println(Thread.currentThread().getName() + " Go out...");
                },String.valueOf(i)).start();
            }
    
            countDownLatch.await(); // 当计数为0,才会执行下面的代码
    
            System.out.println("所有线程都执行完毕了...");
        }
    }

    输出:

    1 Go out...
    2 Go out...
    3 Go out...
    4 Go out...
    5 Go out...
    6 Go out...
    所有线程都执行完毕了..
     

    2、CyclicBarrier

    java.util.concurrent.CyclicBarrier 类,是一个加计数器

    构造方法

    • public CyclicBarrier(int parties) 设置一个需要到达数量的值,到达了parties这个值,不会执行特定的动作
    • public CyclicBarrier(int parties, Runnable barrierAction) 设置一个需要到达数量的值,到达了parties这个值,会执行特定的动作

    常用方法

    • public int await() throws InterruptedException,BrokenBarrierException await方法,该线程进入阻塞状态,屏障值就+1,阻塞线程到达了屏障设定的parties数,就会执行构造器中第二参数barrierAction的动作(第二个参数是Runable接口的实现,通过调用run方法执行)
    • public int getParties() 获得需要达到parties的值
    public class CyclicBarrierTest {
        public static void main(String[] args) {
            // 创建一个加计数器
            CyclicBarrier cyclicBarrier = new CyclicBarrier(6,()-> System.out.println("所有规定的线程都进入到了阻塞状态,达到了屏障"));
    
            for (int i = 1; i <= 6; i++) {
                final int num = i;
                new Thread(()->{
                    System.out.println(Thread.currentThread().getName() + " 执行了");
                  // await方法,该线程进入阻塞状态,屏障值就+1,阻塞线程到达了屏障设定6,就会执行构造器中第二参数的动作(第二个参数是Runable接口的实现,通过调用run方法执行)
                    try {
                        cyclicBarrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " 继续执行");
                }, String.valueOf(i)).start();
            }
        }
    }

    输出:

    1 执行了
    2 执行了
    3 执行了
    4 执行了
    5 执行了
    6 执行了
    所有规定的线程都进入到了阻塞状态,达到了屏障
    6 继续执行
    1 继续执行
    4 继续执行
    3 继续执行
    2 继续执行
    5 继续执行

    3、Semaphore

    java.util.concurrent.Semaphore 类,就是一个许可证(信号量)

    构造方法

    • public Semaphore(int permits) 设置许可证的个数及非公平公平设置
    • public Semaphore(int permits,boolean fair) 设置许可证的个数及给定公平设置

    常用方法

    • public void acquire() throws InterruptedException 获得许可证,未获取到的线程等待。
    • public void release() 释放许可证
    public class SemaphoreTest {
        public static void main(String[] args) {
            // 设置许可证个数。 用于 限流!
            Semaphore semaphore = new Semaphore(3);
            for (int i = 1; i <= 6; i++) {
                new Thread(()->{
                    try {
                        // 线程获取许可证,未获取到的等待。
                        semaphore.acquire();
                        System.out.println(Thread.currentThread().getName() + " 获得许可证");
                        TimeUnit.SECONDS.sleep(2);
                        System.out.println(Thread.currentThread().getName() + " 释放许可证");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        // 释放许可证
                        semaphore.release();
                    }
                }, String.valueOf(i)).start();
            }
        }
    }

    4、Exchanger

    Exchanger类源于java.util.concurrent包,它可以在两个线程之间传输数据,Exchanger中的public V exchange(V x)方法被调用后等待另一个线程到达交换点(如果当前线程没有被中断),然后将已知的对象传给它,返回接收的对象。

    如果担心线程一直等待,可以使用exchange(V x, long timeout, TimeUnit unit)方法设置等待时长。

    public class ExchangerTest {
        private Exchanger<String> exchanger = new Exchanger<>();
        private ExecutorService executorService = Executors.newFixedThreadPool(2);
    
        @Test
        public void test(){
            executorService.execute(()->{
                try {
                    Thread.currentThread().setName("0");
                    String a = "线程A";
                    String B = exchanger.exchange(a); // 与调用这个方法的另一个线程进行数据的交换,
                                                      // 调用了该方法之后,会一直阻塞等待另一个线程进行数据交换
                    System.out.println(Thread.currentThread().getName()+": "+ B);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
    
            executorService.execute(()->{
                try {
                    Thread.currentThread().setName("1");
                    String b = "线程B";
                    String A = exchanger.exchange(b);
                    System.out.println(Thread.currentThread().getName()+": "+ A);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
            });
        }
    }

    - CountDownLatch 与 CyclicBarrier 的区别

    CountDownLatch 是减数的计数器。当值为0后,才使得调用了CountDownLatch的await()方法的线程被唤醒,继续执行之后的任务。并且CountDownLatch不可以重新设置计数总数值

    CyclicBarrier 是加数的计数器,到达了指定的屏障数,才可以被唤醒继续执行。通过线程通过调用CyclicBarrier的await()方法,被阻塞之后,即增加了一个屏障。当达到了屏障指定的数,就会执行特定的动作 (构造器第二个参数barrierAction) 。特定动作执行完了之后,被阻塞的线程会被唤醒,各线程继续执行await()方法之后的任务。CyclicBarrier可以通过reset()方法重置计数器的屏障数

  • 相关阅读:
    [翻译]Webpack解惑
    Vue.js与angular在数据实现的思考
    多线程入门-第三章-线程的调度与控制之优先级
    多线程入门-第二章-线程的生命周期
    多线程入门-第一章-线程的创建与启动
    多线程入门-概述
    IO流入门-第十三章-File相关
    IO流入门-第十二章-ObjectInputStream_ObjectOutputStream
    IO流入门-第十一章-PrintStream_PrintWriter
    IO流入门-第十章-DataInputStream_DataOutputStream
  • 原文地址:https://www.cnblogs.com/turbo30/p/13688206.html
Copyright © 2011-2022 走看看