无法停止使用ExecutorService启动的任务 [英] Can't stop a task which is started using ExecutorService
问题描述
对不起,我要打开一个新的线程来描述这个问题。
Sorry I have to open a new thread to describe this problem.
This morning I asked this question, there're some replies but my problem is still not solved.
这个时候,我会回答这个问题,但是我的问题仍然无法解决。附加一些可运行的代码(简化但具有相同的问题)为您重现问题:
This time I will attach some runnable code(simplified but with the same problem) for you to reproduce the problem:
public class ThreadPoolTest {
public static void main(String[] args) throws Exception {
final ExecutorService taskExecutor = Executors.newFixedThreadPool(5);
Future<Void> futures[] = new Future[5];
for (int i = 0; i < futures.length; ++i)
futures[i] = startTask(taskExecutor);
for (int i = 0; i < futures.length; ++i)
System.out.println("futures[i].cancel(true): " + futures[i].cancel(true));
System.out.println("Cancel DONE.");
taskExecutor.shutdown();
}
private static Future<Void> startTask(final ExecutorService taskExecutor) {
Future<Void> f = taskExecutor.submit(new Callable<Void>() {
public Void call() throws Exception {
try {
downloadFile(new URI("http://stackoverflow.com"));
while(true) {
System.out.println(Thread.currentThread().getName() + ": " + Thread.currentThread().isInterrupted());
if(Thread.currentThread().isInterrupted())
break;
}
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
});
return f;
}
private static void downloadFile (final URI uri) throws Exception {
// if(true) return;
Socket socket = new Socket (uri.getHost(), uri.getPort() == -1 ? 80 : uri.getPort());
return;
}
}
上面的代码很可能被陷入无限循环(你可能想要多次运行代码来证明我看到了什么),正如你在所有任务中调用的 futures [i] .cancel(true)不知道为什么会发生这种情况,这已经折磨我超过一天。
The code above will most likely be trapped in an infinite loop(you may want to run the code multiple times to witness what I saw), as you can see in the main method I have called futures[i].cancel(true) for all tasks, I don't know why this is happening, this has been torturing me for more than a day.
您的帮助将非常感激。
推荐答案
我玩过你的代码,并注意到线程的中断状态有时在套接字创建之前是真的,假后。
I've played with your code, and noticed that the thread's interrupt status is sometimes true before the socket creation, and false after.
我试过中断一个线程并调用Socket构造函数,线程总是保持中断。我也试图删除线程池的关闭,问题继续发生。
I have tried interrupting a thread and calling the Socket constructor, and the thread always stays interrupted after. I also tried removing the shutdown of the threadpool, and the problem continued to happen.
然后我尝试使用5个不同的URI,而不是总是相同的。而且问题从来没有发生过。
Then I have tried using 5 different URIs, rather than always the same one. And the problem never happened.
所以我写了这个简单的程序,显示线程池不是罪魁祸首,但套接字是:
So I wrote this simple program, showing that the thread pool is not the culprit, but the socket is:
public static void main(String[] args) throws Exception {
final URI uri = new URI("http://stackoverflow.com");
for (int i = 0; i < 5; i++) {
Runnable r = new Runnable() {
@Override
public void run() {
Thread.currentThread().interrupt();
System.out.println(Thread.currentThread().isInterrupted());
try {
Socket socket = new Socket (uri.getHost(), uri.getPort() == -1 ? 80 : uri.getPort());
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().isInterrupted());
}
};
new Thread(r).start();
}
}
确实,当5个线程创建一个套接字到同样的主机和端口,其中4个有他们的中断状态清除。
And indeed, when 5 threads create a socket to the same host and port, 4 of them have their interrupt status cleared.
然后我尝试同步套接字创建(在一个单一的锁,但我猜你可能使用一个每个主机/端口锁定):
Then I tried to synchronize the socket creation (on a single lock, but I guess you might use one lock per host/port) :
synchronized(lock) {
try {
Socket socket = new Socket (uri.getHost(), uri.getPort() == -1 ? 80 : uri.getPort());
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
和TADA ...问题消失了。我会在Oracle上打开一个错误以指示问题。
and TADA... the problem disappeared. I would open a bug at Oracle to signal the problem.
这篇关于无法停止使用ExecutorService启动的任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!