无法停止使用ExecutorService启动的任务

对不起,我必须打开一个新线程来描述这个问题。

今天早上我问了这个问题 ,有一些回复,但我的问题仍未解决。

这次我将附加一些可运行的代码(简化但有相同的问题),以便您重现问题:

public class ThreadPoolTest { public static void main(String[] args) throws Exception { final ExecutorService taskExecutor = Executors.newFixedThreadPool(5); Future 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 startTask(final ExecutorService taskExecutor) { Future f = taskExecutor.submit(new Callable() { 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; } } 

上面的代码很可能被困在一个无限循环中(你可能想多次运行代码来见证我所看到的),正如你在main方法中看到的那样,我称之为future [i] .cancel(true) for所有的任务,我不知道为什么会这样,这已经让我折磨了一天多。

对你的帮助表示感谢。

我玩过你的代码,并注意到线程的中断状态有时在套接字创建之前是真的,之后是假的。

我试过打断一个线程并调用Socket构造函数,然后线程总是保持中断状态。 我也尝试删除线程池的关闭,问题继续发生。

然后我尝试使用5个不同的URI,而不是总是相同的URI。 问题从未发生过。

所以我编写了这个简单的程序,表明线程池不是罪魁祸首,但套接字是:

 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个线程的中断状态被清除。

然后我尝试同步套接字创建(在单个锁上,但我想你可能每个主机/端口使用一个锁):

 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上打开一个错误来表示问题。

我运行你的代码,并没有像你说的那样停止。

没有太多时间来调查它为什么会这样,但我发现将执行程序服务的线程声明为守护程序会使问题消失:

 private static ExecutorService TaskExecutor = Executors.newFixedThreadPool(5, new ThreadFactory() { public Thread newThread(Runnable r) { Thread t = new Thread(r); t.setDaemon(true); return t; } }); 

如果我找到更好的解释,我会回来的。

我认为当您尝试取消任务时,任务未启动的问题。 我添加了Thread.sleep(100)如下所示:

 for (int i = 0; i < futures.length; ++i) futures[i] = startTask(taskExecutor); Thread.sleep(100); for (int i = 0; i < futures.length; ++i) System.out.println("futures[i].cancel(true): " + futures[i].cancel(true)); 

一切都被取消了。