zoukankan      html  css  js  c++  java
  • Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo

    Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo

    CountDownLatch

    countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。

    是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。

    CountDownLatch中的方法

    //调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
    public void await() throws InterruptedException { };   
    //和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
    public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };  
    //将count值减1
    public void countDown() { };  
    

    CountDownLatchDemo

    条件改为i<20时,并不会输出“完结撒花”,因为latch还没有减到0

    import java.util.concurrent.CountDownLatch;
    
    public class CountDownLatchDemo {
        public static void main(String[] args)  {
            CountDownLatch latch = new CountDownLatch(20);
            //条件改为i<20时,并不会输出“完结撒花”,因为latch还没有减到0
            for (int i = 0; i < 20; i++) {
                int index=i;
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        latch.countDown();
                        System.out.println(index);
                    }
                }).start();
            }
            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("完结撒花");
        }
    }
    

    CyclicBarrier

    CyclicBarrier可以使一定数量的线程反复地在栅栏位置处汇集。当线程到达栅栏位置时将调用await方法,这个方法将阻塞直到所有线程都到达栅栏位置。如果所有线程都到达栅栏位置,那么栅栏将打开,此时所有的线程都将被释放,而栅栏将被重置以便下次使用。

    • CountDownLatch 是一次性的,CyclicBarrier 是可循环利用的

    构造方法

    public CyclicBarrier(int parties)
    public CyclicBarrier(int parties, Runnable barrierAction)
    
    • parties 是参与线程的个数
    • 第二个构造方法有一个 Runnable 参数,这个参数的意思是最后一个到达线程要做的任务

    方法

    public int await() throws InterruptedException, BrokenBarrierException
    public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException
    
    • 线程调用 await() 表示自己已经到达栅栏
    • BrokenBarrierException 表示栅栏已经被破坏,破坏的原因可能是其中一个线程 await() 时被中断或者超时

    Demo

    • 初始化线程1,线程1睡眠3秒
    • 剩余九个线程到达barrier,但是并不会又输出
    • 三秒后线程1到达,9个线程开始输出
    import java.util.concurrent.BrokenBarrierException;
    import java.util.concurrent.CyclicBarrier;
    
    public class CyclicBarrierDemo {
        public static void main(String[] args) {
            CyclicBarrier barrier = new CyclicBarrier(10);
            //初始化线程1,线程1睡眠3秒,等待剩余九个线程到达barrier
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.currentThread().sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    try {
                        barrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            //九个线程先到达barrier
            for (int i = 0; i < 9; i++) {
                int index=i;
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            barrier.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        } catch (BrokenBarrierException e) {
                            e.printStackTrace();
                        }
                        System.out.println(index);
                    }
                }).start();
            }
        }
    }
    //Output,输出是随机的
    /*
            0
            6
            2
            1
            8
            7
            4
            3
            5*/
    

    Semaphore

    Semaphore也是一个线程同步的辅助类,可以维护当前访问自身的线程个数,并提供了同步机制。使用Semaphore可以控制同时访问资源的线程个数,例如,实现一个文件允许的并发访问数。

    常用方法

      void acquire():从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。
    
      void release():释放一个许可,将其返回给信号量。
    
      int availablePermits():返回此信号量中当前可用的许可数。
    
      boolean hasQueuedThreads():查询是否有线程正在等待获取。
    
    

    Demo

    • 六个人竞争三个办事窗口,每个办事窗口只能容纳三个人,输出如下
    package ConcurrentApi;
    
    import java.util.concurrent.Semaphore;
    //Output
    /*
        线程0等到了办事窗口空闲
                办事窗口剩余量2
        线程1等到了办事窗口空闲
                办事窗口剩余量1
        线程2等到了办事窗口空闲
                办事窗口剩余量0
        线程3等到了办事窗口空闲
                办事窗口剩余量0
        线程4等到了办事窗口空闲
                办事窗口剩余量0
        线程5等到了办事窗口空闲
                办事窗口剩余量0*/
    public class SemaphoreDemo {
        public static void main(String[] args) {
            //初始化3 三个办事窗口
            Semaphore semaphore = new Semaphore(3);
            for (int i = 0; i < 6; i++) {
                int index = i;
                try {
                    Thread.currentThread().sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            semaphore.acquire();
                            System.out.println("线程"+index+"等到了办事窗口空闲");
                            System.out.println("办事窗口剩余量"+semaphore.availablePermits());
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        try {
                            Thread.currentThread().sleep(4000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        semaphore.release();
                    }
                }).start();
            }
        }
    }
    
  • 相关阅读:
    Codeforces 632D 暴力
    Codeforces 632C
    nyoj 1070 诡异的电梯 简单dp
    Codeforces 6225B KMP
    Codeforces 631D
    笔记4:多层感知器(自定义模型)
    笔记3:逻辑回归(分批次训练)
    笔记2:张量简介
    笔记1:入门实例
    送快递(贪心+树形结构)
  • 原文地址:https://www.cnblogs.com/aslanvon/p/15194556.html
Copyright © 2011-2022 走看看