【发布时间】:2016-06-16 05:18:58
【问题描述】:
我想知道创建不终止的 Java 线程的最佳方法是什么。 目前,我基本上有一个“跑步者”,基本上看起来像:
ExecutorService pool = Executors.newFixedThreadPool(3);
for (int i = 0; i < numThreads; ++i) {
pool.submit(new Task());
}
pool.shutdown();
Task 看起来像这样
public class Task {
...
public void run() {
while(true) { }
}
}
我的方法有两个顾虑:
我是否应该创建一个在完成工作后才返回的任务并继续生成执行最少工作量的线程?我担心开销,但不知道如何衡量它。
如果我有一个无限循环的线程,当我强制退出可执行文件时,这些线程会被关闭并清理吗?经过一些测试,当包含ExecutorService的代码被强制关闭时,并没有出现InterruptException。
编辑: 详细地说,任务看起来像
public void run() {
while(true) {
// Let queue be a synchronized, global queue
if (queue has an element) {
// Pop from queue and do a very minimal amount of work on it
// Involves a small amount of network IO (maybe 10-100 ms)
} else {
sleep(2000);
}
}
}
【问题讨论】:
-
这两个问题实际上取决于
while(true){}块内的内容。它是在旋转、休眠、阻塞 I/O 还是什么? -
创建线程池是没有意义的,但你只是为每个线程运行forever-loop。对于您打算做的事情,最好的办法是:让一个专用线程从队列中读取。每当它获得一个元素时,然后通过创建一个短暂运行的
Task来处理该元素并使用线程池执行它 -
嘿@erickson:刚刚添加了编辑。基本上它会在网络 IO 上休眠或阻塞(我希望计算量最小)
-
另外,你应该使用阻塞队列,然后线程将被阻塞,直到有一个元素可以从队列中取出,并且不需要那种hacky sleep。见docs.oracle.com/javase/8/docs/api/java/util/concurrent/…
-
@DLevant 我喜欢这个想法,但它只是概念上的队列,而不是实际的队列。不确定我是否有权将队列代码修改为“阻塞”。
标签: java multithreading executorservice threadpoolexecutor