Java多线程编程七 同步计数器

线程同步计数器

利用线程池进行线程开发使用时,因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();//当前可用的许可数。
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。