ThreadPoolExecutor - ArrayBlockingQueue ...在从队列中删除元素之前等待

时间:2010-10-04 23:48:21

标签: java multithreading thread-safety threadpool blockingqueue

我正在尝试调整执行以下操作的线程:

只有1个帖子[CorePoolSize =0, maxPoolSize = 1]

的线程池

使用的队列是ArrayBlockingQueue

Quesize = 20

背景
线程尝试读取请求并对其执行操作。

然而,最终请求增加了很多,以至于线程总是很忙并占用1个CPU,这使得它成为一种资源浪费。

我想做什么,而是定期对请求进行采样并处理它们。其他请求可以安全地忽略。

我需要做的是在“操作”功能中进行休眠,以便每个任务线程都会休眠一段时间并释放CPU。

Quesiton:
但是,我想知道是否有一种方法可以使用一个基本上自己在读取下一个元素之前休眠一段时间的队列。这是理想的,因为在执行过程中睡眠任务并保持执行不完整对我来说听起来不是最好的。

如果您对任务有任何其他建议,请告知我们

感谢。

编辑: 我添加了一个后续问题here 将maxpool size更正为1 [急忙写] ..感谢蒂姆指出它。

4 个答案:

答案 0 :(得分:1)

不,你不能让线程在池中睡觉。如果队列中有任务,它将被执行。

在排队任务中暂停是强制线程在排队任务时处于空闲状态的唯一方法。现在,“睡眠”不必与“工作”处于同一任务中 - 您可以在每个真实任务之后对单独的休息任务进行排队,这可能会使实现更清晰。更重要的是,如果工作是Callable返回结果,则分成两个任务将允许您尽快获得结果。

作为一种改进,您可以“限制”执行到指定的速率,而不是在每个任务之间固定间隔睡眠。这将允许您避免在任务之间不必要地等待,但避免在指定的时间间隔内执行太多任务。您可以read another answer of mine使用DelayQueue以简单的方式实现此目的。

答案 1 :(得分:1)

您可以继承ThreadPool并覆盖beforeExecute以暂停一段时间:

@Overrides
protected void beforeExecute(Thread t,
                         Runnable r){
    try{
       Thread.sleep( millis);  // will sleep the correct thread, see JavaDoc
    }
    catch (InterruptedException e){}

  }

但是看到AngerClown关于人为地放慢队列速度的评论可能不是一个好主意。

答案 2 :(得分:1)

这可能不适合您,但您可以尝试将执行程序的线程优先级设置为低。

基本上,使用自定义ThreadPoolExecutor创建ThreadFactory。让ThreadFactory.newThread()方法返回优先级为Thread.MIN_PRIORITY的线程。这将导致您使用的执行程序服务仅在有可用核心运行时才进行调度。

含义:在严格使用时间切片的系统上,如果整个程序中没有其他线程要求进行调度,则只会给出一个时间片来执行。根据应用程序的实际繁忙程度,您可能会偶尔安排一次,或者根本不会安排。

答案 3 :(得分:1)

线程占用100%CPU的原因是因为它给予的工作量超过了它可以处理的工作量。在任务之间添加延迟不会解决此问题。这只是让事情变得更糟。

相反,您应该看看为什么您的任务消耗了如此多的CPU,例如使用分析器并更改它们以便消耗更少的CPU,直到您发现您的线程可以跟上并且它不再消耗100%的CPU。