使用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