countdownlatch线程计数器(等待所有线程搞定,主线程才继续)
用法
比如有一个任务 A,它要等待其他 4 个任务执行完毕之后才能执行,此时就可以利用CountDownLatc来实现这种功能了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| final CountDownLatch latch = new CountDownLatch(2); new Thread(){public void run() { System.out.println("子线程"+Thread.currentThread().getName()+"正在执行"); Thread.sleep(3000); System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕"); latch.countDown(); };}.start(); new Thread(){ public void run() { System.out.println("子线程"+Thread.currentThread().getName()+"正在执行"); Thread.sleep(3000); System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕"); latch.countDown(); };}.start();
System.out.println("等待 2 个子线程执行完毕...");
latch.await();
System.out.println("2 个子线程已经执行完毕"); System.out.println("继续执行主线程"); }
|
cyclicBarrier(回环栅栏,让一组线程等待至某个状态之后再全部同时执行)
回环
因为当所有等待线程都被释放以后,CyclicBarrier 可以被重用。
barrier
当调用 await()方法之后,线程就处于 barrier 了。
用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| 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(); } static class Writer extends Thread{ private CyclicBarrier cyclicBarrier; public Writer(CyclicBarrier cyclicBarrier) { this.cyclicBarrier = cyclicBarrier; } @Override public void run() { 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("所有线程写入完毕,继续处理其他任务,比如数据操作"); } }
|
semaphore信号量(控制同时访问线程个数)
Semaphore 可以控制同时访问的线程个数,通过acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。
用法
例子:若一个工厂有 5 台机器,但是有 8 个工人,一台机器同时只能被一个工人使用,只有使用完
了,其他工人才能继续使用。那么我们就可以通过 Semaphore 来实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 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(); } }
|
使用场景
CountDownLatch 和 CyclicBarrier 都能够实现线程之间的等待,只不过它们侧重点不同;
- CountDownLatch 一般用于某个线程 A 等待若干个其他线程执行完任务之后,它才执行;
- CyclicBarrier 一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行;另外,CountDownLatch 是不能够重用的,而 CyclicBarrier 是可以重用的。
- Semaphore 其实和锁有点类似,它一般用于控制对某组资源的访问权限。