Can't stop a task which is started using ExecutorService

浪子不回头ぞ 提交于 2019-12-06 02:43:47

I've played with your code, and noticed that the thread's interrupt status is sometimes true before the socket creation, and false after.

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.

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();
    }
}

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();
    }
}

and TADA... the problem disappeared. I would open a bug at Oracle to signal the problem.

I ran your code, and it didn't stop, as you said.

Didn't have much time to investigate why it behaves so, but I found out that declaring the executor service's threads as daemons made the problem go away :

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

I'll come back if I find a better explanation.

I think the problem that task are not started when you try to cancel them. I added Thread.sleep(100) like this:

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));

and everything was cancelled ok.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!