有没有办法创建Executor,它总是至少有5个线程,最多20个线程,以及任务的无限队列(意味着没有任务被拒绝)
我尝试了新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
并且没有按预期工作。
答案 0 :(得分:5)
这样的事情对你有用吗?我只是把它掀起来所以请捅它。基本上,它实现了一个溢出线程池,用于提供底层ThreadPoolExecutor
我看到它有两个主要的缺点:
submit()
上缺少返回的Future对象。但也许这对你来说不是问题。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);
}
}
答案 1 :(得分:1)
ThreadPoolExecutor
的javadoc非常清楚,一旦创建corePoolSize
个线程,只有队列满了才会创建新线程。因此,如果您将core
设置为5并将max
设置为20,那么您将无法获得所需的行为。
但是,如果将core
和max
都设置为20,那么只有当所有20个线程都忙时,才会将任务添加到队列中。当然,这会使你的“5线程最小”要求变得毫无意义,因为所有20个都将保持活着(直到它们闲置,无论如何)。
答案 2 :(得分:1)
我认为这个问题是类的缺点,并且在给定构造函数参数组合的情况下会产生误导。这是从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();
}
}
}