线程同步计数器
利用线程池进行线程开发使用时,因join方法使用不便而引入了线程同步计数器。
CountDownLatch计数器
通过代理变量sync 实现AbstractQueuedSynchronizer接口。
CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1,当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。
CountDownLatch中主要方法如下:
public CountDownLatch(int count);//,构造函数中的count(计数器)实际上就是闭锁需要等待的线程数量,这个值只能被设置一次,而且CountDownLatch没有提供任何机制去重新设置这个计数值。
public void countDown();//每调用一次这个方法,在构造函数中初始化的count值就减1,通知机制是此方法来完成的。
public void await() throws InterruptedException//调用此方法的当前线程会一直阻塞,直到计时器的值为0。
简单使用
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(11);
ExecutorService service = Executors.newFixedThreadPool(7);
int i =1;
Runnable runnable = ()->{
System.out.println("countDownLatch前"+Thread.currentThread().getName());
countDownLatch.countDown();
/*try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}*/
System.out.println("countDownLatch后"+Thread.currentThread().getName());
};
for(int j = 0; j < 10;j++)
service.execute(runnable);
countDownLatch.await();
System.out.println("hello"+countDownLatch.getCount());
service.shutdown();
}
CyclicBarrier回环屏障
通过代理的独占锁实现
public CyclicBarrier(int parties);
public CyclicBarrier(int parties, Runnable barrierAction);
public int await() throws InterruptedException, BrokenBarrierException
public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException
线程调用 await() 表示自己已经到达栅栏
BrokenBarrierException 表示栅栏已经被破坏,破坏的原因可能是其中一个线程 await() 时被中断或者超时
所有线程会等待全部线程到达栅栏之后才会继续执行,并且最后到达的线程会完成 Runnable 的任务。
CyclicBarrier和CountDownLatch的区别
CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以使用reset()方法重置,可以使用多次,所以CyclicBarrier能够处理更为复杂的场景;
CyclicBarrier还提供了一些其他有用的方法,比如getNumberWaiting()方法可以获得CyclicBarrier阻塞的线程数量,isBroken()方法用来了解阻塞的线程是否被中断;
CountDownLatch允许一个或多个线程等待一组事件的产生,而CyclicBarrier用于等待其他线程运行到栅栏位置。
Semaphore信号量
通过代理变量sync 实现AbstractQueuedSynchronizer接口。
Semaphore 是一个计数信号量,必须由获取它的线程释放。
常用于限制可以访问某些资源的线程数量,例如通过 Semaphore 限流。
Semaphore 只有3个操作:初始化 增加 减少
Semaphore(int permits);//构造方法,创建具有给定许可数的计数信号量并设置为非公平信号量。
Semaphore(int permits,boolean fair);//构造方法,当fair等于true时,创建具有给定许可数的计数信号量并设置为公平信号量。
void acquire();//从此信号量获取一个许可前线程将一直阻塞。相当于一辆车占了一个车位。
void acquire(int n);//从此信号量获取给定数目许可,在提供这些许可前一直将线程阻塞。比如n=2,就相当于一辆车占了两个车位。
void release();//释放一个许可,将其返回给信号量。就如同车开走返回一个车位。
void release(int n);//释放n个许可。
int availablePermits();//当前可用的许可数。