JUC下的并发工具

Semaphore-控制并发线程数

  • 信号量,用来限制能够同时访问共享资源的线程上限
  • Semaphore可以用来流量控制,在线程数大于资源数时,用来限制线程数;比如数据库连接池的改进

基本使用

@Slf4j
public final class Demo{
    public static void main(String[] args){
        // 创建Semaphore对象,限制为3
        Semaphore semaphore = new Semaphore(3);

        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                try {
                    // 表示从semaphore中获取共享资源获取许可
                    semaphore.acquire();
                    log.debug("get resource");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    // 释放资源
                    semaphore.release();
                }
            },"t"+i).start();
        }
    }
}

其他方法

  • int availablePermits():返回此信号量中当前可用的许可证数
  • int getQueueLength():返回正在等待获取许可证的线程数
  • boolean hasQueuedThreads():是否有线程正在等待获取许可证
  • protected void reducePermits(int reduction):减少reduction个许可证
  • protected Collection getQueuedThreads():返回所有获取许可证的线程集合

CountdownLatch-等待多线程完成

  • 用来进行线程同步,等待一个或多个其他线程完成操作
  • 其中构造参数用来初始化等待计数值,await()用来等待计数归零,countDown()用来让计数减一
  • 首先创建一个等待计数,调用await进入阻塞,然后每个线程执行完毕就让计数减一,当计数为0时,线程将会被唤醒
@Slf4j
public final class Demo{
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(3);

        new Thread(()->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.debug("t1 finished");
            countDownLatch.countDown();
        },"t1").start();

        new Thread(()->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.debug("t2 finished");
            countDownLatch.countDown();
        },"t2").start();

        new Thread(()->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.debug("t3 finished");
            countDownLatch.countDown();
        },"t3").start();

        countDownLatch.await();
        log.debug("main resume");
    }
}

CyclicBarrier-同步屏障

  • CyclicBarrier字面意思是可循环使用的屏障,他要做的事是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行
  • CyclicBarrier可以用于多线程计算数据,最后合并计算结果的场景
@Slf4j
public final class Demo{
    public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
        new Thread(()->{
            try {
                // 调用await方法表示已经到达了屏障
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
            log.debug("t1 continue");
        },"t1").start();

        new Thread(()->{
            try {
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
            log.debug("t2 continue");
        },"t2").start();

        Thread.sleep(3000);
        cyclicBarrier.await();

        log.debug("main continue");
    }
}

CyclicBarrier和CountDownLatch的区别

  • CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以使用reset方法重置,所以CyclicBarrier可以处理更为复杂的业务场景,比如如果计算发生错误,可以重置计数器,并且让线程重新执行
  • CyclicBarrier还提供了其他方法,比如getNumberWaiting可以获得阻塞的线程数量、isBroken方法可以用来了解阻塞的线程是否被中断

Exchanger-线程间交换数据

Exchanger是一个用于线程间写作的工具类,进行线程间的数据交换。他提供一个同步点,在这个同步点,两个线程可以交换彼此的数据。

@Slf4j
public final class Demo{
    public static void main(String[] args){
        Exchanger<String> exchanger = new Exchanger<>();
        new Thread(()->{
            try {
                String rec = exchanger.exchange("t1");
                log.debug(rec);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t1").start();

        new Thread(()->{
            try {
                String rec = exchanger.exchange("t2");
                log.debug(rec);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t2").start();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值