我正在使用固定大小的Java线程池(ExecutorService)。假设我向线程池提交了一个作业,并且该作业处于空闲状态。
是否有可能从线程池中删除空闲作业,以便可以处理队列中的其他作业,然后稍后再次添加空闲作业?
如果你从ExecutorService
移动到 ThreadPoolExecutor,你可以使用以下 API 来实现它
public void setCorePoolSize(int corePoolSize)
设置线程的核心数。这将覆盖构造函数中设置的任何值。如果新值小于当前值,则多余的现有线程将在下次空闲时终止。
如果更大,如果需要,将启动新线程以执行任何排队的任务。
如果要在运行时调整池的大小,
((ThreadPoolExecutor)service).setCorePoolSize(newLimit);
//newLimit 是池的新大小
其他接口:
public void setMaximumPoolSize(int maximumPoolSize)
设置允许的最大线程数。这将覆盖构造函数中设置的任何值。如果新值小于当前值,则多余的现有线程将在下次空闲时终止。
或Runnable
可能处于idle
(我想等待I/O或其他资源)这一事实是主要原因之一,因为适合使用线程池。
另一方面,您需要调整要使用的线程量,以便在某些线程被阻塞等待资源时处理任务。
您唯一需要做的就是观察线程进入空闲状态的频率,并相应地调整线程量。
调优 ThreadPool 的指南(来自:IBM ThreadPool 和 Work Queue)
不要将同步等待其他任务结果的任务排队。这可能会导致上述形式的死锁,其中所有线程都被任务占用,这些任务又在等待排队任务的结果,这些任务由于所有线程都繁忙而无法执行。
将池化线程用于可能长期存在的操作时要小心。如果程序必须等待资源(如 I/O 完成),请指定最长等待时间,然后失败或重新排队等待任务,以便稍后执行。这保证了最终将通过释放线程来执行可能成功完成的任务来取得一些进展。
了解您的任务。要有效地调整线程池大小,您需要了解正在排队的任务以及它们正在执行的操作。它们是否受 CPU 限制?它们是否受 I/O 限制?您的答案将影响您调整应用程序的方式。如果您有具有截然不同特征的不同类别的任务,则为不同类型的任务设置多个工作队列可能是有意义的,因此可以相应地调整每个池。