java

juc常用类: CountDownLatch、CyclicBar

2020-12-29  本文已影响0人  修行者12138

CountDownLatch

CountDownLatch是计数器,作用是阻塞主线程,直到若干子线程都执行完毕,再继续执行主线程,比如阻塞餐厅的服务员(不让他开门),等到所有顾客都赶到了(顾客是子线程,赶路是线程的操作),服务员才开门。

CyclicBarrier

CyclicBarrier是循环栅栏,作用是:一个或多个线程都执行完一部分操作后,再一起执行另一部分操作,比如所有顾客都赶到餐厅后,服务员才开门,然后顾客才可以一起吃饭;
CyclicBarrier也可以达到CountDownLatch的效果;
CyclicBarrier可以循环利用,CountDownLatch不行。

Semaphore

Semaphore意为信号量,用于限制访问某个资源的线程数,比如限制同一时间餐厅只能容纳三个顾客。

CountDownLatch使用示例

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.util.concurrent.*;

/**
 * CountDownLatch示例类
 *
 * CountDownLatch作用:
 * CountDownLatch是一个计数器,通过构造函数传入count,表示有count个子线程
 * 用await方法阻塞主线程
 * 每个子线程执行完毕后,通过countDown函数把计数器-1,countDown为0表示子线程执行完毕,主线程继续执行
 *
 * ThreadPoolExecutor的awaitTermination()能达到同样的效果
 *
 */
public class CountDownLatchDemo {
    public static void main(String[] args) throws Exception{
        System.out.println("主线程开始执行");
        int limit = 5;
        CountDownLatch countDownLatch = new CountDownLatch(limit);

        ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat("CountDownLatchDemo-pool-%d").build();
        ThreadPoolExecutor pool = new ThreadPoolExecutor(limit, limit, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingDeque<>(1024), factory, new ThreadPoolExecutor.AbortPolicy());

        for (int i = 0; i < limit; i++) {
            pool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (countDownLatch) {
                        countDownLatch.countDown();
                        System.out.println("子线程开始执行,name: " + Thread.currentThread().getName() + ", countDownLatch.getCount(): " + countDownLatch.getCount());
                    }
                }
            });
        }

        pool.shutdown();
        countDownLatch.await();
        System.out.println("子线程执行完毕,主线程继续执行");
    }
}

输出结果

主线程开始执行
子线程开始执行,name: CountDownLatchDemo-pool-2, countDownLatch.getCount(): 4
子线程开始执行,name: CountDownLatchDemo-pool-1, countDownLatch.getCount(): 3
子线程开始执行,name: CountDownLatchDemo-pool-0, countDownLatch.getCount(): 2
子线程开始执行,name: CountDownLatchDemo-pool-3, countDownLatch.getCount(): 1
子线程开始执行,name: CountDownLatchDemo-pool-4, countDownLatch.getCount(): 0
子线程执行完毕,主线程继续执行

CyclicBarrier示例代码

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.util.concurrent.*;

/**
 * CyclicBarrier示例类
 *
 * CyclicBarrier作用:
 * CyclicBarrier意为循环栅栏,栅栏相当于一个门,一开始栅栏关闭着,所有子线程先执行一部分操作,都到达栅栏后,栅栏才开启,然后所有子线程再一起执行下一部分操作。
 * 可以把CyclicBarrier比喻成餐厅的门,所有顾客都到了,餐厅才开门,然后顾客才可以吃饭。
 * 之所以叫循环栅栏,是因为CyclicBarrier的reset方法可以重置栅栏。
 *
 */
public class CyclicBarrierDemo {

    public static void main(String[] args) {
        int limit = 5;
        CyclicBarrier cyclicBarrier = new CyclicBarrier(5, new Runnable() {
            @Override
            public void run() {
                // 栅栏开启时,主线程的操作
                System.out.println("开启栅栏");
            }
        });

        ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat("CyclicBarrierDemo-pool-%d").build();
        ThreadPoolExecutor pool = new ThreadPoolExecutor(limit, limit, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingDeque<>(1024), factory, new ThreadPoolExecutor.AbortPolicy());

        for (int i = 0; i < limit; i++) {
            pool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        // 栅栏开启前子线程的操作
                        Thread.sleep(1000);
                        System.out.println("子线程" + Thread.currentThread().getName() + "开始等待");

                        // await方法会阻塞子线程至栅栏开启
                        cyclicBarrier.await();

                        // 栅栏开启后子线程的操作
                        System.out.println("子线程" + Thread.currentThread().getName() + "开始执行");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        pool.shutdown();
    }

}

输出结果

子线程CyclicBarrierDemo-pool-1开始等待
子线程CyclicBarrierDemo-pool-0开始等待
子线程CyclicBarrierDemo-pool-4开始等待
子线程CyclicBarrierDemo-pool-2开始等待
子线程CyclicBarrierDemo-pool-3开始等待
开启栅栏
子线程CyclicBarrierDemo-pool-3开始执行
子线程CyclicBarrierDemo-pool-1开始执行
子线程CyclicBarrierDemo-pool-2开始执行
子线程CyclicBarrierDemo-pool-4开始执行
子线程CyclicBarrierDemo-pool-0开始执行

Semaphore示例代码

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.util.concurrent.*;

/**
 * Semaphore示例类
 *
 * Semaphore作用:
 * Semaphore意为信号量,用于限制访问某个资源的线程数
 *
 */
public class SemaphoreDemo {

    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(3);
        int threadCount = 10;
        ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat("SemaphoreDemo-pool-%d").build();
        ThreadPoolExecutor pool = new ThreadPoolExecutor(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingDeque<>(1024), factory, new ThreadPoolExecutor.AbortPolicy());

        for (int i = 0; i < threadCount; i++) {
            pool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        // 获取信号量
                        semaphore.acquire();
                        System.out.println("子线程" + Thread.currentThread().getName() + "开始执行");
                        Thread.sleep(1000);
                        System.out.println("子线程" + Thread.currentThread().getName() + "执行完毕");
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        // release方法放到finally,确保可以释放信号量
                        semaphore.release();
                    }
                }
            });
        }

        pool.shutdown();
    }
}

输出结果

子线程SemaphoreDemo-pool-0开始执行
子线程SemaphoreDemo-pool-1开始执行
子线程SemaphoreDemo-pool-2开始执行
子线程SemaphoreDemo-pool-0执行完毕
子线程SemaphoreDemo-pool-3开始执行
子线程SemaphoreDemo-pool-1执行完毕
子线程SemaphoreDemo-pool-2执行完毕
子线程SemaphoreDemo-pool-4开始执行
子线程SemaphoreDemo-pool-5开始执行
子线程SemaphoreDemo-pool-3执行完毕
子线程SemaphoreDemo-pool-4执行完毕
子线程SemaphoreDemo-pool-5执行完毕
子线程SemaphoreDemo-pool-7开始执行
子线程SemaphoreDemo-pool-6开始执行
子线程SemaphoreDemo-pool-8开始执行
子线程SemaphoreDemo-pool-8执行完毕
子线程SemaphoreDemo-pool-7执行完毕
子线程SemaphoreDemo-pool-6执行完毕
子线程SemaphoreDemo-pool-9开始执行
子线程SemaphoreDemo-pool-9执行完毕
上一篇下一篇

猜你喜欢

热点阅读