使用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();

}

});

}

实际结果

疑问

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

回答

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

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

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

以上是 使用ThreadPoolExecutor并用Threed.sleep模拟任务执行,实际sleep实际不准确且远长于设置时间 的全部内容, 来源链接: utcz.com/a/43855.html

回到顶部