我有以下代码,每次针对不同数量的线程执行:
class Worker<T> {
public void process() {
System.out.pritnln("Test");
}
}
class Processor {
private void doStuff(final Collection<Worker<V>> col) {
final int size = col.size();
if (size > 0) {
final ExecutorService threads = Executors.newFixedThreadPool(col.size());
for (Worker<V> w : col) {
threads.submit(() -> w.process());
}
threads.shutdown();
}
}
}
每次都在新的民意调查标识符中打印:
(池-66 线程-1( 测试
(池-66 线程-2( 测试
(池-67 线程-1( 测试
(池-68 线程-1(测试
(池-68-线程-3( 测试
(池-68 线程-2( 测试
我想知道这是否是常见的行为,或者在某些时候内存泄漏并且会爆炸。它不应该重用以前的pools
吗?
我怎么看,由于threads.shutdown()
电话,以前的那些池已经shutdown
我想知道这是否是常见的行为,或者在某些时候内存泄漏并且会爆炸。它不应该重用以前的池吗?
好吧,您一直在显式创建新池。
// this creates a new pool
final ExecutorService threads = Executors.newFixedThreadPool(col.size());
至于内存泄漏,由于您正在关闭池,这应该没问题(但您应该finally
安全地执行此操作,以防万一有例外(。
如果要重用池(这完全有意义(,则应threads
Processor
的实例变量(并确保Processor implements AutoCloseable
并在close方法中关闭threads
(。
你在函数中调用Executors.newFixedThreadPool()
,这会创建一个新的线程池。
这本身并没有错,但它并不常见,并且违背了使用线程池背后的许多动机。更标准的方法是在Processor
类中创建单个线程池,并向其调度作业,如下所示:
class Processor {
private final ExecutorService service = Executors.newFixedThreadExecutor(count);
private void doStuff() {
...
...
service.submit(() -> w.process());
}
}
拥有线程池的想法是限制您正在创建的线程数量并重用已经创建的线程,以避免在给定时间处理大量线程的不必要的拥塞并使其更有效率。现在你的代码的问题是它既不限制线程数,也不重用。由于您只执行一些打印,因此您可能不会看到拥塞,但是如果您在工作线程中添加更多处理并保持并行调用它,那么您会看到完成处理的严重延迟。