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

 



原文地址:https://www.cnblogs.com/whtblog/p/8919731.html