使用ThreadPoolExecutor并用Threed.sleep模拟任务执行,实际sleep实际不准确且远长于设置时间

新手上路,请多包涵

问题描述

我自己创建了一个ThreadPoolExecutor,并且在执行任务时使用Threed.sleep(2000)模拟任务执行的时间消耗,但是在实测当中Threed.sleep(2000)的等待时间除了开始有些是2s以外,后续等待时间越来越长,甚至超过一分钟,不清楚是为什么。

示例代码

 AtomicInteger curPage = new AtomicInteger(-1);
 int limit = 10;
 // 分页查询数据
 long totalCount = dataRepository.count();
 // 获取总页数
 int totalPage = (int) Math.ceil(totalCount / limit);
 AtomicInteger remainPage = new AtomicInteger(totalPage);
 // 获取当前时间戳
 Long now = LocalDateTime.now().atZone(ZoneId.systemDefault()).toEpochSecond();
 // 创建用于处理任务的线程池
 ExecutorService executors = new ThreadPoolExecutor(20, 20, 0L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
 // 循环处理每页数据
 while (remainPage.get() > 0) {
    executors.execute(() -> {
        // 进入循环,总页数减一,当前页翻页,查询数据
        remainPage.decrementAndGet();
        curPage.incrementAndGet();
        
        System.out.println("curPage: " + curPage.get() + " --- " + "remainPage: " + remainPage.get());
        try {
            long time = System.currentTimeMillis();
            Thread.sleep(2000);
            System.out.println("释放!!!!---- time: " + (System.currentTimeMillis() - time));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
 }

实际结果

image.png

疑问

查询了下没找到相关描述,非常疑惑这个地方为什么差距会这么大。

阅读 3.3k
3 个回答

Thread.sleep(2000);只是定时唤醒,至于线程什么时候抢到cpu资源是个问题。
remainPage比较大时,while大量执行抢占cpu,decrementAndGet()incrementAndGet()并发也是大量抢占cpu,sleep()唤醒之后,都在等上面的decrementAndGet、incrementAndGet

不是sleep的问题,是cas操作并发大拖慢了
remainPage.decrementAndGet();放到任务外面就好了

1.remainPage.decrementAndGet(); 放在while下一句。
2.由于1中没有控制,会一下次涌进来很多次执行executors.execute。
3.线程池线程只设置20个,多余的任务都到LinkedBlockingQueue里去了,队列里的任务就需要等待空闲线程执行。随意会造成远大于2000ms的情况

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题