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 }
子线程Thread-0正在执行 main等待2个子线程执行完毕... 子线程Thread-1正在执行 子线程Thread-0执行完毕 子线程Thread-1执行完毕 2个子线程已经执行完毕 继续执行主线程
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()+"所有线程写入完毕,继续处理其他任务..."); } } }
线程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所有线程写入完毕,继续处理其他任务...
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(); } } } }
工人1占用一个机器在生产...
工人2占用一个机器在生产...
工人0占用一个机器在生产...
工人4占用一个机器在生产...
工人3占用一个机器在生产...
工人1释放出机器
工人5占用一个机器在生产...
工人0释放出机器
工人6占用一个机器在生产...
工人2释放出机器
工人3释放出机器
工人4释放出机器
工人7占用一个机器在生产...
工人5释放出机器
工人6释放出机器
工人7释放出机器