天下之事,必先处之难,而后易之。

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永远是异常处理完成之后释放资源的最佳方式。

posted @   boonya  阅读(20)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
历史上的今天:
2020-09-04 JavaScript Ajax 取消请求防重处理(完美解决LBS轮询重复刷新问题)
我有佳人隔窗而居,今有伊人明月之畔。
轻歌柔情冰壶之浣,涓涓清流梦入云端。
美人如娇温雅悠婉,目遇赏阅适而自欣。
百草层叠疏而有致,此情此思怀彼佳人。
念所思之唯心叩之,踽踽彳亍寤寐思之。
行云如风逝而复归,佳人一去莫知可回?
深闺冷瘦独自徘徊,处处明灯影还如只。
推窗见月疑是归人,阑珊灯火托手思忖。
庐居闲客而好品茗,斟茶徐徐漫漫生烟。

我有佳人在水之畔,瓮载渔舟浣纱归还。
明月相照月色还低,浅近芦苇深深如钿。
庐山秋月如美人衣,画堂春阁香气靡靡。
秋意幽笃残粉摇曳,轻轻如诉画中蝴蝶。
泾水潺潺取尔浇园,暮色黄昏如沐佳人。
青丝撩弄长裙翩翩,彩蝶飞舞执子手腕。
香带丝缕缓缓在肩,柔美体肤寸寸爱怜。
如水之殇美玉成欢,我有佳人清新如兰。
伊人在水我在一边,远远相望不可亵玩。

点击右上角即可分享
微信分享提示