Java 指定ThreadPoolExecutor问题
是否有任何方法可以创建始终至少有5个线程、最多20个线程以及任务无限队列(意味着没有任务被拒绝)的Executor 我尝试了新的Java 指定ThreadPoolExecutor问题,java,multithreading,threadpool,Java,Multithreading,Threadpool,是否有任何方法可以创建始终至少有5个线程、最多20个线程以及任务无限队列(意味着没有任务被拒绝)的Executor 我尝试了新的ThreadPoolExecutor(5,20,60L,TimeUnit.SECONDS,queue) 我想到了队列的所有可能性: new LinkedBlockingQueue() // never runs more than 5 threads new LinkedBlockingQueue(1000000) // runs more than 5 threads
ThreadPoolExecutor(5,20,60L,TimeUnit.SECONDS,queue)
我想到了队列的所有可能性:new LinkedBlockingQueue() // never runs more than 5 threads
new LinkedBlockingQueue(1000000) // runs more than 5 threads, only when there is more than 1000000 tasks waiting
new ArrayBlockingQueue(1000000) // runs more than 5 threads, only when there is more than 1000000 tasks waiting
new SynchronousQueue() // no tasks can wait, after 20, they are rejected
而且没有一个线程可以正常工作。ThreadPoolExecutor的javadocs非常清楚,一旦创建了
corePoolSize
线程,只有在队列已满时才会创建新线程。因此,如果您将core
设置为5,将max
设置为20,您将永远无法获得所需的行为
但是,如果将
core
和max
都设置为20,则只有当所有20个线程都忙时,任务才会添加到队列中。当然,这会使您的“最少5个线程”要求变得有点毫无意义,因为所有20个线程都将保持活动状态(直到它们空闲掉为止)。也许这样的要求对您适用?我刚把它搅起来,请戳一下。基本上,它实现了一个溢出线程池,用于为底层ThreadPoolExecutor
我看到它有两个主要的缺点:
上缺少返回的未来对象。但也许这不是你的问题submit()
- 提交作业时,辅助队列将仅清空到
中。必须有一个优雅的解决方案,但我现在还没有看到。如果您知道将有一个稳定的任务流进入ThreadPoolExecutor
,那么这可能不是问题。(“可能”是关键词。)一种选择可能是让您提交的任务在完成后戳到StusMagicExecutor
StusMagicExecutor
public class StusMagicExecutor extends ThreadPoolExecutor {
private BlockingQueue<Runnable> secondaryQueue = new LinkedBlockingQueue<Runnable>(); //capacity is Integer.MAX_VALUE.
public StusMagicExecutor() {
super(5, 20, 60L, SECONDS, new SynchronousQueue<Runnable>(true), new RejectionHandler());
}
public void queueRejectedTask(Runnable task) {
try {
secondaryQueue.put(task);
} catch (InterruptedException e) {
// do something
}
}
public Future submit(Runnable newTask) {
//drain secondary queue as rejection handler populates it
Collection<Runnable> tasks = new ArrayList<Runnable>();
secondaryQueue.drainTo(tasks);
tasks.add(newTask);
for (Runnable task : tasks)
super.submit(task);
return null; //does not return a future!
}
}
class RejectionHandler implements RejectedExecutionHandler {
public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) {
((StusMagicExecutor)executor).queueRejectedTask(runnable);
}
}
公共类StusMagicExecutor扩展ThreadPoolExecutor{
private BlockingQueue secondaryQueue=new LinkedBlockingQueue();//容量为Integer.MAX_值。
公共行政主管(){
super(5,20,60L,秒,新的SynchronousQueue(true),新的RejectionHandler());
}
公共无效队列拒绝任务(可运行任务){
试一试{
secondaryQueue.put(任务);
}捕捉(中断异常e){
//做点什么
}
}
公共未来提交(可运行的newTask){
//在拒绝处理程序填充辅助队列时将其排出
收集任务=新建ArrayList();
secondaryQueue.drainTo(任务);
任务。添加(newTask);
for(可运行任务:任务)
超级提交(任务);
return null;//不返回未来!
}
}
类RejectionHandler实现RejectedExecutionHandler{
public void rejectedExecution(Runnable Runnable,ThreadPoolExecutor executor){
((StusMagicExecutor)执行器)。队列拒绝任务(可运行);
}
}
我认为这个问题是该类的一个缺点,并且考虑到构造函数参数组合,它非常容易引起误解。这是一个来自SwingWorker的内部ThreadPoolExecutor的解决方案,我将其制作成一个顶级类。它没有最小值,但至少使用了上界。我唯一不知道的是锁定执行对性能的影响
public class BoundedThreadPoolExecutor extends ThreadPoolExecutor {
private final ReentrantLock pauseLock = new ReentrantLock();
private final Condition unpaused = pauseLock.newCondition();
private boolean isPaused = false;
private final ReentrantLock executeLock = new ReentrantLock();
public BoundedThreadPoolExecutor(int maximumPoolSize,
long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(0, maximumPoolSize, keepAliveTime, unit, workQueue);
}
public BoundedThreadPoolExecutor(int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
super(0, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory);
}
public BoundedThreadPoolExecutor(int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
super(0, maximumPoolSize, keepAliveTime, unit, workQueue,
handler);
}
public BoundedThreadPoolExecutor(int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
super(0, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, handler);
}
@Override
public void execute(Runnable command) {
executeLock.lock();
try {
pauseLock.lock();
try {
isPaused = true;
} finally {
pauseLock.unlock();
}
setCorePoolSize(getMaximumPoolSize());
super.execute(command);
setCorePoolSize(0);
pauseLock.lock();
try {
isPaused = false;
unpaused.signalAll();
} finally {
pauseLock.unlock();
}
} finally {
executeLock.unlock();
}
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
pauseLock.lock();
try {
while (isPaused) {
unpaused.await();
}
} catch (InterruptedException ignore) {
} finally {
pauseLock.unlock();
}
}
}
public类BoundedThreadPoolExecutor扩展ThreadPoolExecutor{
private final ReentrantLock pauseLock=new ReentrantLock();
private final Condition unpaused=pauseLock.newCondition();
私有布尔值isPaused=false;
private final ReentrantLock executeLock=new ReentrantLock();
public BoundedThreadPoolExecutor(int maximumPoolSize,
long keepAliveTime、时间单位、阻塞队列(工作队列){
super(0,maximumPoolSize,keepAliveTime,unit,workQueue);
}
public BoundedThreadPoolExecutor(int maximumPoolSize,
长keepAliveTime,时间单位,
BlockingQueue工作队列,ThreadFactory ThreadFactory){
超级(0,maximumPoolSize,keepAliveTime,unit,workQueue,
螺纹加工厂);
}
public BoundedThreadPoolExecutor(int maximumPoolSize,
长keepAliveTime,时间单位,
BlockingQueue工作队列,RejectedExecutionHandler){
超级(0,maximumPoolSize,keepAliveTime,unit,workQueue,
经办人);
}
public BoundedThreadPoolExecutor(int maximumPoolSize,
长keepAliveTime,时间单位,
BlockingQueue工作队列,ThreadFactory ThreadFactory,
RejectedExecutionHandler(处理程序){
超级(0,maximumPoolSize,keepAliveTime,unit,workQueue,
螺纹加工厂、处理厂);
}
@凌驾
public void execute(Runnable命令){
executeLock.lock();
试一试{
pauseLock.lock();
试一试{
isPaused=真;
}最后{
pauseLock.unlock();
}
setCorePoolSize(getMaximumPoolSize());
super.execute(命令);
setCorePoolSize(0);
pauseLock.lock();
试一试{
isPaused=false;
unpaused.signalAll();
}最后{
pauseLock.unlock();
}
}最后{
executeLock.unlock();
}
}
@凌驾
执行后受保护的无效(可运行的r、可丢弃的t){
super.afterExecute(r,t);
pauseLock.lock();
试一试{
while(isPaused){
等待;
}
}捕获(中断异常忽略){
}最后{
pauseLock.unlock();
}
}
}
你说它不起作用是什么意思?一个例外?这太接近了:甘道夫和萨蒙!急诊室随时都会来。那个讨厌的老鹰在哪里…“闲置”永远不会发生,除非你们说所有的核心线程都可能死亡。无论如何,如果不能正确使用,就看不到核心和最大尺寸的意义