Java并发编程实践:CountDownLatch模拟并发请求及注意事项

目录

原子锁使用CountDownLatch 

使用CountDownLatch的注意事项


原子锁使用CountDownLatch 

  • 原子锁:Atomic*类的封装类型,如:AtomicInteger、AtomicLong。
  • CountDownLatch: 是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程执行完后再执行,CountDownLatch比较通俗的叫法是闭锁(栅栏),当值为0时就绪否则等待阻塞,最形象的就像赛马,发令枪不响所有马和运动员只能等。
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @ClassName: ConcurrencyTest
 * @Description: TODO(功能说明:模拟并发请求)
 * @author: pengjunlin
 * @motto: 学习需要毅力,那就秀毅力
 * @date 2020/3/1 22:45
 */
public class ConcurrencyTest {

    // 请求总数
    public static int clientTotal = 5000;

    // 原子锁
    public static AtomicInteger count = new AtomicInteger(0);

    public static void main(String[] args) throws Exception {
        ExecutorService executorService = Executors.newCachedThreadPool();

        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
        for (int i = 0; i < clientTotal ; i++) {
            executorService.execute(() -> {
                countDownLatch.countDown();
                try {
                    countDownLatch.await();
                    add();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }

        try{
            //直到方法执行完成
            Thread.sleep(10000);
            executorService.shutdown();
            System.out.println(count);
        }catch(InterruptedException e){
            e.printStackTrace();
        }
    }

    private static void add() {
        count.incrementAndGet();
    }
}

使用CountDownLatch的注意事项

使用CountDownLatch需要注意避免阻塞,即调用await()一定要确保可以countDown()使最终结果得以执行下去而不是永远阻塞。在实际应用中尤其要注意计数递减一定要保证最终回归到0的状态,确保解除阻塞等待。如示例:

/**
     * 消费数据
     * @param count
     */
    public void consumeOnlineData(int count){
        // 控制每次处理的量
        if (count > queueConsumeNumber) {
            count = queueConsumeNumber;
        }
        // 计数器控制任务是否获取的条件
        countDownLatch = new CountDownLatch(count);
        for (int i = 0; i < count; i++) {
            UserPosition xhyPosition = MobileDataQueue.getOnlineQueue().poll();
            if (ObjectUtils.isNotEmpty(xhyPosition)) {
                if (ObjectUtils.isNotEmpty(MobileDataQueue.executorService)) {
                    MobileDataQueue.executorService.execute(() -> {
                        try{
                            MobileDataQueue.positionRedisPipelineService.online(xhyPosition);
                        }catch (Exception e){
                            e.printStackTrace();
                        }finally {
                            countDownLatch.countDown();
                        }
                    });
                } else {
                    MobileDataQueue.threadPoolExecutor.execute(() -> {
                        try{
                            MobileDataQueue.positionRedisPipelineService.online(xhyPosition);
                        }catch (Exception e){
                            e.printStackTrace();
                        }finally {
                            countDownLatch.countDown();
                        }
                    });
                }
            }else{
                countDownLatch.countDown();
            }
        }

        try {
            // 线程阻塞直到任务执行完成
            log.info("===========[MSG]ONLINE队列中批量消费=====await ....");
            countDownLatch.await();
            log.info("===========[MSG]ONLINE队列中批量消费=====finish");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

可以人为干预await()阻塞的时长,也可以起到解除阻塞的作用:

   try {
            // 线程阻塞直到任务执行完成
            log.info("===========[MSG]ONLINE队列中批量消费=====await ....");
            countDownLatch.await(10, TimeUnit.SECONDS);
            log.info("===========[MSG]ONLINE队列中批量消费=====finish");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

注意:try catch finally 语句很重要,finally永远是异常处理完成之后释放资源的最佳方式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值