(01) CountDownLatch的作用是允许1或N个线程等待其他线程完成执行;而CyclicBarrier则是允许N个线程相互等待。
(02) CountDownLatch的计数器无法被重置;CyclicBarrier的计数器可以被重置后使用,因此它被称为是循环的barrier。
关于CyclicBarrier的原理,后面一章再来学习。
CountDownLatch是通过“共享锁”实现的。在创建CountDownLatch中时,会传递一个int类型参数count,该参数是“锁计数器”的初始状态,表示该“共享锁”最多能被count给线程同时获取。当某线程调用该CountDownLatch对象的await()方法时,该线程会等待“共享锁”可用时,才能获取“共享锁”进而继续运行。而“共享锁”可用的条件,就是“锁计数器”的值为0!而“锁计数器”的初始值为count,每当一个线程调用该CountDownLatch对象的countDown()方法时,才将“锁计数器”-1;通过这种方式,必须有count个线程调用countDown()之后,“锁计数器”才为0,而前面提到的等待线程才能继续运行!
public class My { static CountDownLatch countDownLatch = new CountDownLatch(5); public static void main(String[] args) { // TODO Auto-generated method stub try { for (int i = 0; i < 5; i++) { new MyT().start(); } System.out.println(Thread.currentThread().getName() + "wait"); countDownLatch.await(); System.out.println(Thread.currentThread().getName() + "run"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } static class MyT extends Thread { @Override public void run() { try { sleep(1000); System.out.println(Thread.currentThread().getName() + " sleep 1000ms."); countDownLatch.countDown(); } catch (Exception e) { // TODO: handle exception } } } }
dowait()的作用就是让当前线程阻塞,直到“有parties个线程到达barrier” 或 “当前线程被中断” 或 “超时”这3者之一发生,当前线程才继续执行。
public class My { static CyclicBarrier barrier = new CyclicBarrier(5); public static void main(String[] args) { for (int i = 0; i < 5; i++) { new MyT().start(); } System.out.println(Thread.currentThread().getName() + "wait"); System.out.println(Thread.currentThread().getName() + "run"); } static class MyT extends Thread { @Override public void run() { try { sleep(1000); System.out.println(Thread.currentThread().getName() + " sleep 1000ms."); barrier.await(); } catch (Exception e) { // TODO: handle exception } } } }
Semaphore是一个计数信号量,它的本质是一个"共享锁"。
信号量维护了一个信号量许可集。线程可以通过调用acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。
import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.Semaphore; public class My { static CyclicBarrier barrier = new CyclicBarrier(5); public static void main(String[] args) { Semaphore sem = new Semaphore(10); new MyT(sem, 3).start(); new MyT(sem, 5).start(); new MyT(sem, 7).start(); } static class MyT extends Thread { private volatile Semaphore sem; private int c; public MyT(Semaphore sem, int c) { this.sem = sem; this.c = c; } @Override public void run() { try { sem.acquire(c); System.out.println(Thread.currentThread().getName() + " sleep 1000ms."); Thread.sleep(1000); } catch (Exception e) { // TODO: handle exception }finally { sem.release(c); } } } }
时间: 2024-10-03 14:15:01