zoukankan      html  css  js  c++  java
  • Java并发机制(8)--concurrent包下辅助类的使用

    Java并发编程:concurrent包下辅助类的使用

    整理自:博客园-海子-http://www.cnblogs.com/dolphin0520/p/3920397.html

    1、CountDownLatch用法:

      count到达0之前,调用await()的线程会一直等待,count不能重用。

      1.1、构造与方法:

    CountDownLatch(int count) 构造一个用给定计数初始化的 CountDownLatch
    
    await() 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断(InterruptedException异常)。
    
    countDown() 递减锁存器的计数,如果计数到达零,则释放所有等待的线程。 

      1.2、实例:

     1 public class Test {
     2     public static void main(String[] args) {   
     3         final CountDownLatch latch = new CountDownLatch(2);
     4          
     5         new Thread(){
     6             public void run() {
     7                 try {
     8                     System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
     9                    Thread.sleep(3000);
    10                    System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
    11                    latch.countDown();
    12                } catch (InterruptedException e) {
    13                    e.printStackTrace();
    14                }
    15             };
    16         }.start();
    17          
    18         new Thread(){
    19             public void run() {
    20                 try {
    21                     System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
    22                     Thread.sleep(3000);
    23                     System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
    24                     latch.countDown();
    25                } catch (InterruptedException e) {
    26                    e.printStackTrace();
    27                }
    28             };
    29         }.start();
    30          
    31         try {
    32             System.out.println(Thread.currentThread().getName()+"等待2个子线程执行完毕...");
    33            latch.await();
    34            System.out.println("2个子线程已经执行完毕");
    35            System.out.println("继续执行主线程");
    36        } catch (InterruptedException e) {
    37            e.printStackTrace();
    38        }
    39     }
    40 }
    View Code
    子线程Thread-0正在执行
    main等待2个子线程执行完毕...
    子线程Thread-1正在执行
    子线程Thread-0执行完毕
    子线程Thread-1执行完毕
    2个子线程已经执行完毕
    继续执行主线程
    result

    2、CyclicBarrier用法:

      回环栅栏,作用同上,让一组线程等待某个状态(barrier状态)后再同时开始执行,CyclicBarrier可以被重用。

      2.1构造与方法:

    CyclicBarrier(int parties) : 创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动
    CyclicBarrier(int parties, Runnable barrierAction) :创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动barrierAction。
    await(): 在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。(等待知道barrier上的线程数达到parties)

      2.2实例:

    public class Test {
        public static void main(String[] args) {
            int N = 4;
            CyclicBarrier barrier  = new CyclicBarrier(N);
             
            for(int i=0;i<N;i++) {
                new Writer(barrier).start();
            }
             
            try {
                Thread.sleep(25000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
             
            System.out.println("CyclicBarrier重用");
             
            for(int i=0;i<N;i++) {
                new Writer(barrier).start();
            }
        }
        static class Writer extends Thread{
            private CyclicBarrier cyclicBarrier;
            public Writer(CyclicBarrier cyclicBarrier) {
                this.cyclicBarrier = cyclicBarrier;
            }
     
            @Override
            public void run() {
                System.out.println("线程"+Thread.currentThread().getName()+"正在写入数据...");
                try {
                    Thread.sleep(5000);      //以睡眠来模拟写入数据操作
                    System.out.println("线程"+Thread.currentThread().getName()+"写入数据完毕,等待其他线程写入完毕");
                 
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }catch(BrokenBarrierException e){
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"所有线程写入完毕,继续处理其他任务...");
            }
        }
    }
    View Code
    线程Thread-3正在写入数据...
    线程Thread-0正在写入数据...
    线程Thread-2正在写入数据...
    线程Thread-1正在写入数据...
    线程Thread-3写入数据完毕,等待其他线程写入完毕
    线程Thread-0写入数据完毕,等待其他线程写入完毕
    线程Thread-1写入数据完毕,等待其他线程写入完毕
    线程Thread-2写入数据完毕,等待其他线程写入完毕
    Thread-3所有线程写入完毕,继续处理其他任务...
    Thread-0所有线程写入完毕,继续处理其他任务...
    Thread-1所有线程写入完毕,继续处理其他任务...
    Thread-2所有线程写入完毕,继续处理其他任务...
    CyclicBarrier重用
    线程Thread-4正在写入数据...
    线程Thread-6正在写入数据...
    线程Thread-5正在写入数据...
    线程Thread-7正在写入数据...
    线程Thread-7写入数据完毕,等待其他线程写入完毕
    线程Thread-6写入数据完毕,等待其他线程写入完毕
    线程Thread-4写入数据完毕,等待其他线程写入完毕
    线程Thread-5写入数据完毕,等待其他线程写入完毕
    Thread-5所有线程写入完毕,继续处理其他任务...
    Thread-7所有线程写入完毕,继续处理其他任务...
    Thread-6所有线程写入完毕,继续处理其他任务...
    Thread-4所有线程写入完毕,继续处理其他任务...
    result

    3、Semaphore用法:信号量

      semaphore可以控制同时访问的线程个数,通过 acquire() 获取一个许可,release()释放一个许可;

      3.1、构造与方法  

    Semaphore(int permits)创建具有给定的许可数和非公平的公平设置的 Semaphore。
    Semaphore(int permits, boolean fair)  创建具有给定的许可数和给定的公平设置的 Semaphore。
    
    //acquire为阻塞方法,一直等待信号量,直到获取到许可;
    acquire((int permits)): 从此信号量获取一个(permits个)许可,在这之前,线程被阻塞;
    release((int permits)) : 释放一个(permits个)许可,将其返回给信号量。
    //tryAcquir能立即返回是否能获取许可
    tryAcquire(int permits),(long timeout, TimeUnit unit)):尝试或一定时间内尝试获取许可,成功返回true,失败返回false。

      3.2、使用实例:

    //假若一个工厂有5台机器,但是有8个工人,一台机器同时只能被一个工人使用,只有使用完了,其他工人才能继续使用
    public class Test {
        public static void main(String[] args) {
            int N = 8;            //工人数
            Semaphore semaphore = new Semaphore(5); //机器数目
            for(int i=0;i<N;i++)
                new Worker(i,semaphore).start();
        }
         
        static class Worker extends Thread{
            private int num;
            private Semaphore semaphore;
            public Worker(int num,Semaphore semaphore){
                this.num = num;
                this.semaphore = semaphore;
            }
             
            @Override
            public void run() {
                try {
                    semaphore.acquire();
                    System.out.println("工人"+this.num+"占用一个机器在生产...");
                    Thread.sleep(2000);
                    System.out.println("工人"+this.num+"释放出机器");
                    semaphore.release();           
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    View Code
    工人1占用一个机器在生产...
    工人2占用一个机器在生产...
    工人0占用一个机器在生产...
    工人4占用一个机器在生产...
    工人3占用一个机器在生产...
    工人1释放出机器
    工人5占用一个机器在生产...
    工人0释放出机器
    工人6占用一个机器在生产...
    工人2释放出机器
    工人3释放出机器
    工人4释放出机器
    工人7占用一个机器在生产...
    工人5释放出机器
    工人6释放出机器
    工人7释放出机器
    result

     



  • 相关阅读:
    【Leetcode_easy】852. Peak Index in a Mountain Array
    【Leetcode_easy】849. Maximize Distance to Closest Person
    【Leetcode_easy】844. Backspace String Compare
    【Leetcode_easy】840. Magic Squares In Grid
    【Leetcode_easy】836. Rectangle Overlap
    【Leetcode_easy】832. Flipping an Image
    【Leetcode_easy】830. Positions of Large Groups
    【Leetcode_easy】824. Goat Latin
    【Leetcode_easy】821. Shortest Distance to a Character
    【Leetcode_easy】819. Most Common Word
  • 原文地址:https://www.cnblogs.com/whtblog/p/8919731.html
Copyright © 2011-2022 走看看