我试图使用ThreadPoolExecutor来调度任务,但是它的策略遇到了一些问题。以下是它声明的行为:
我想要的行为是:
基本上,我不希望任何任务被拒绝;我希望它们在一个无界队列中排队。但我确实想拥有最多的maximumPoolSize线程。如果我使用一个无界队列,它在访问coreSize之后就不会生成线程。如果我使用有界队列,它会拒绝任务。有办法绕过这件事吗?
我现在想的是在一个ThreadPoolExecutor上运行SynchronousQueue,而不是直接将任务提供给它,而是将它们提供给一个单独的、无界的LinkedBlockingQueue。然后,另一个线程从LinkedBlockingQueue输入到执行器,如果一个线程被拒绝,它只需再试一次,直到未被拒绝。这似乎是一种痛苦和一些黑客,尽管-有一个更干净的方法来做到这一点吗?
发布于 2010-08-06 08:01:50
您的用例是常见的,完全合法,不幸的是,它比人们预期的更困难。对于背景信息,您可以阅读这一讨论并找到指向解决方案的指针(在线程中也提到) 这里。谢伊的解决方案很好。
通常,我会对无界队列有点警惕;通常最好有显式的传入流控制,这种控制会优雅地降低,并调节当前/剩余工作的比率,而不会压倒生产者或消费者。
发布于 2010-08-06 06:01:49
可能没有必要在请求时对线程池进行微管理。
缓存的线程池将重用空闲线程,同时也允许潜在的无限并发线程。当然,这可能会导致失控的性能,在突发期间由于上下文切换开销而降低。
Executors.newCachedThreadPool();一个更好的选择是限制线程总数,同时放弃确保首先使用空闲线程的概念。配置更改将是:
corePoolSize = maximumPoolSize = N;
allowCoreThreadTimeOut(true);
setKeepAliveTime(aReasonableTimeDuration, TimeUnit.SECONDS);如果执行器的线程少于corePoolSize线程,则对此方案的推理不能太忙。如果系统不是很忙,那么纺出一个新线程几乎没有什么害处。这样做将导致ThreadPoolExecutor始终创建一个新的工作人员,如果它低于允许的最大工人数。只有当最大数量的工作人员在“运行”时,才会给空闲等待任务的工人分配任务。如果工作人员在没有任务的情况下等待aReasonableTimeDuration,则允许它终止。使用池大小的合理限制(毕竟,只有这么多CPU)和相当大的超时(以防止线程不必要地终止),可能会看到所需的好处。
最后一种选择是冷嘲热讽。基本上,ThreadPoolExecutor内部使用BlockingQueue.offer来确定队列是否具有容量。BlockingQueue的自定义实现总是可以拒绝offer尝试。当ThreadPoolExecutor无法将任务放到队列中时,它将尝试创建一个新的工作人员。如果无法创建新员工,则将调用RejectedExecutionHandler。此时,自定义RejectedExecutionHandler可以强制put进入自定义BlockingQueue。
/** Hackish BlockingQueue Implementation tightly coupled to ThreadPoolexecutor implementation details. */
class ThreadPoolHackyBlockingQueue<T> implements BlockingQueue<T>, RejectedExecutionHandler {
BlockingQueue<T> delegate;
public boolean offer(T item) {
return false;
}
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
delegate.put(r);
}
//.... delegate methods
}发布于 2010-08-05 21:41:04
只需设置corePoolsize = maximumPoolSize并使用无界队列?
在你的点数列表中,1不包括2,因为corePoolSize总是小于或等于maximumPoolSize。
编辑
在你想要的东西和TPE会提供给你的东西之间仍然有一些不相容的东西。
如果您有一个无界队列,maximumPoolSize就会被忽略,因此,正如您所观察到的,将只创建和使用corePoolSize线程。
所以,再次,如果您使用一个无限制队列的corePoolsize = maximumPoolSize,您就有您想要的了,不是吗?
https://stackoverflow.com/questions/3419380
复制相似问题