早在90年代,当java开始被开发时,机器甚至没有现在的十分之一的资源。。。多线程是"多线程";概念";和硬件限制是主要的关注点,也是软件开发每一步的主要关注点
接口Executor及其所有已知的主要实现都来自21世纪初,并且是按照的思维方式设计的
但情况发生了很大的变化
每次我想使用Executor时,我都会遇到问题。。。比方说:
new ThreadPoolExecutor(3, 10, 60L, TimeUnit.MINUTES, new LinkedBlockingQueue(20));
此语句将创建一个池,其中包含3个"常开"线程、最多10个活动线程和20个的等待列表
但它的实现有点像
如果核心池有空间添加否则,如果等待列表有空间添加到等待列表else if有空间扩展线程池添加
这样,如果核心池已满,执行器将在尝试扩展核心池之前将新任务添加到等待列表中。。。
对于今天的应用来说,这个方法并不理想(更不用说无用(
从2000年到今天,Java已经更新了数百次,但我仍然不知道Executitor的任何官方实现有这种行为->在添加到等待列表之前扩展池
是否有这样的实现(不为此导入整个API(?
如何创建具有这种行为的类?
对于标准的ThreadPoolExecutor,您可以设置:
- corePoolSize到最大预期线程数
- maxPoolSize设置为相同值
- 保持AliveTime和单位为合理值
,然后调用allowsCoreThreadTimeOut(true(在实际任务调度之前。
因此,与将任务添加到等待列表相比,扩展池将更可取。
唯一的副作用是核心工作人员也将在keepAliveTime到期后完成。但是,可以通过为该参数选择合理的值来最小化这种影响。
我通过
public class ThreadPoolExpandableExecutor extends ThreadPoolExecutor {
public ThreadPoolExpandableExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, Executors.defaultThreadFactory());
}
public ThreadPoolExpandableExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, ThreadFactory threadFactory) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, new InternalLinkedBlockingQueue(), threadFactory);
this.setRejectedExecutionHandler(new InternalRejectedExecutionHandler(this.getQueue()));
}
@Override
public synchronized void execute(Runnable command) {
super.execute(command);
};
@Override
public synchronized <T extends Object> java.util.concurrent.Future<T> submit(java.util.concurrent.Callable<T> task) {
return super.submit(task);
};
private static final class InternalRejectedExecutionHandler implements RejectedExecutionHandler {
private final BlockingQueue<Runnable> queue;
private InternalRejectedExecutionHandler(BlockingQueue<Runnable> queue) {
this.queue = queue;
}
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
this.queue.put(r);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private static final class InternalLinkedBlockingQueue extends LinkedBlockingQueue<Runnable> {
private static final long serialVersionUID = 1L;
private InternalLinkedBlockingQueue() {
super(Integer.MAX_VALUE);
}
@Override
public boolean offer(Runnable e) {
return false;
}
}
此类将始终启用核心池大小如果在corepool已满但maxpool有空间时提交了新任务,则会立即创建并启动一个新线程如果在核心池已满且最大池已满的情况下提交了新任务,它将被添加到任务队列中
该解决方案远非完美,我创建了一个队列实现,它总是拒绝新项目但让他们用看跌方法推进
只有当你(像我一样(不在乎有一个无限的任务队列时,它才有效