zoukankan      html  css  js  c++  java
  • 线程池中的栅栏

    多线程中有三个类,分别是CountDownLatch,CyclicBarrier,Semaphore。代表着线程中的栅栏。共享锁。

    CountDownLatch

    在一组线程中,一个线程等待其他线程。我把它理解为门栓。

    查看该类的数据结构图如下图一

    ​ 图一

    有一个静态的内部类,Sync继承自AQS。

    • CountDownLatch(int) : 有参构造方法,该类拥有的共享锁次数。
    • await() : 阻塞,等待该类释放掉共享锁,也就是说,拥有共享锁的次数为0
    • countDown:释放一次共享锁
    • getCount: 获取共享锁次数

    使用例子:代码如下:

    
    /**
     * @ClassName CountDownLatchTest
     * @Description 共享锁。在完成一组正在其他线程中执行的操作之前,允许一个或者多个线程一直等待
     * @Author ouyangkang
     * @Date 2018/10/23 14:33
     **/
    public class CountDownLatchTest {
        private static int SIZE = 6;
    
        private static CountDownLatch countDownLatch;
    
        /**
         * @Date 2018/10/25 15:49
         * @Description 阻塞队列为3 核心池的大小为2 最大池的大小为6的线程池
         **/
        private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                2, 6, 60L,TimeUnit.SECONDS, new LinkedBlockingDeque<>(3));
    
        public static void main(String[] args) {
            countDownLatch = new CountDownLatch(SIZE);
    
            for (int i = 0; i < 6; i++) {
                threadPoolExecutor.execute(new ThreadTest());
            }
    
            try {
                // 阻塞等待
                countDownLatch.await();
                System.out.printf("thread main = [{%s}] 
    ", Thread.currentThread().getName());
                threadPoolExecutor.shutdown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    
        static class ThreadTest extends Thread {
            @Override
            public void run() {
                System.out.printf("thread-name = [%s] 
    ", Thread.currentThread().getName());
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.printf("thread-name =[%s] 执行 
    ", Thread.currentThread().getName());
    
                // 数值减一
                countDownLatch.countDown();
            }
        }
    }
    

    返回结果:

    thread-name = [pool-1-thread-1] 
    thread-name = [pool-1-thread-3] 
    thread-name = [pool-1-thread-2] 
    thread-name =[pool-1-thread-1] 执行 
    thread-name =[pool-1-thread-3] 执行 
    thread-name = [pool-1-thread-1] 
    thread-name = [pool-1-thread-3] 
    thread-name =[pool-1-thread-2] 执行 
    thread-name = [pool-1-thread-2] 
    thread-name =[pool-1-thread-1] 执行 
    thread-name =[pool-1-thread-3] 执行 
    thread-name =[pool-1-thread-2] 执行 
    thread main = [{main}] 
    
    • 线程池中阻塞队列为3,启动了6个线程。阻塞队列中阻塞3个,核心池2个在执行任务,最大池的大小为6,那么就会新建一个线程来处理该任务。
    • 主线程最后执行,wait等待其他线程任务执行完毕,再继续执行主线程。

    CyclicBarrier

    在一组线程中允许多个线程相互等待。就是,每个线程都先执行一下,然后互相等待到一个点。然后再执行。

    查看该类的数据结构图

    有参构造方法,设置屏障点是多少,创建线程,等待。直到线程数量大于等于该屏障点。处于该屏障点等待得线程全部唤醒。

    使用例子如下:

    
    /**
     * @ClassName CyclicBarrierTest
     * @Description 屏障,允许多个线程相互等待。到达了某一个临界点,就唤醒所有线程
     * @Author ouyangkang
     * @Date 2018/10/23 15:00
     **/
    public class CyclicBarrierTest {
    
        private static int SIZE = 5;
        
        private static CyclicBarrier cyclicBarrier;
    
        public static void main(String[] args) {
            cyclicBarrier = new CyclicBarrier(SIZE);
            for (int i = 0; i < 5 ;i++){
                new ThreadTest().start();
            }
        }
    
        static class ThreadTest extends Thread {
            @Override
            public void run() {
                System.out.printf("thread=[%s] 开始-- 
    ", Thread.currentThread().getName());
    
                try {
                    Thread.sleep(1000);
                    cyclicBarrier.await();
                    System.out.printf("thread=[%s] 继续--- 
    ", Thread.currentThread().getName());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    结果如下:

    thread=[Thread-0] 开始-- 
    thread=[Thread-4] 开始-- 
    thread=[Thread-3] 开始-- 
    thread=[Thread-1] 开始-- 
    thread=[Thread-2] 开始-- 
    thread=[Thread-2] 继续--- 
    thread=[Thread-4] 继续--- 
    thread=[Thread-0] 继续--- 
    thread=[Thread-1] 继续--- 
    thread=[Thread-3] 继续--- 
    

    Semaphore

    在一组线程中,线程持有信号量,如果信息量得大小为10,那么所有线程能够持有得信号量不能超过10,如果3个线程分别持有得信号量是3 4 5 。 那么只能是两个线程运行,当其中一个释放了该信号量,其他线程才可以运行。

    类图结构如下:

    具体例子如下:

    
    /**
     * @ClassName SemaphoreTest
     * @Description 信号量
     * @Author ouyangkang
     * @Date 2018/10/23 16:34
     **/
    public class SemaphoreTest {
    
    
    
        private static int SIZE = 10;
    
    
        public static void main(String[] args) {
            Semaphore semaphore = new Semaphore(SIZE);
            ExecutorService executorService = new  ThreadPoolExecutor(2,3,60L,TimeUnit.SECONDS,new LinkedBlockingQueue<>(5));
            executorService.execute(new ThreadTest(3,semaphore));
            executorService.execute(new ThreadTest(4,semaphore));
            executorService.execute(new ThreadTest(5,semaphore));
            executorService.shutdown();
        }
    
    
        static class ThreadTest extends Thread{
    
            private Integer count ;
    
            private Semaphore semaphore;
    
            public ThreadTest(Integer count , Semaphore semaphore){
                this.count = count ;
                this.semaphore = semaphore;
            }
            @Override
            public void run() {
                try {
                    semaphore.acquire(count);
                    System.out.printf("thread=[%s]  拥有信号量 semaphore=[%d] 开始---- 
    ",Thread.currentThread().getName(), count);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    semaphore.release(count);
                    System.out.printf("thread=[%s] 释放了 semaphore=[%d] --
    ",Thread.currentThread().getName(),count);
                }
    
    
            }
        }
    }
    

    具体结果如下:

    thread=[pool-1-thread-2]  拥有信号量 semaphore=[4] 开始---- 
    thread=[pool-1-thread-1]  拥有信号量 semaphore=[3] 开始---- 
    thread=[pool-1-thread-2] 释放了 semaphore=[4] --
    thread=[pool-1-thread-2]  拥有信号量 semaphore=[5] 开始---- 
    thread=[pool-1-thread-1] 释放了 semaphore=[3] --
    thread=[pool-1-thread-2] 释放了 semaphore=[5] --
    
  • 相关阅读:
    第二章 Centos7下Confluence7.4.0安装
    第一章 APM基本介绍
    第二十一章 MySQL导入数据常见报错解决
    第二十章 Centos7 下 Mysql 8.0.24编译安装
    第一章 Confluence基础介绍
    第十九章 Centos7下 Mysql 8.0.24 二进制安装
    团队项目冲刺阶段一(5)
    团队项目冲刺阶段一(4)
    团队项目冲刺阶段一(3)
    团队项目冲刺阶段一(2)
  • 原文地址:https://www.cnblogs.com/Krloypower/p/9869072.html
Copyright © 2011-2022 走看看