【问题标题】:Thread.interrupt is not called when using ExecutorService使用 ExecutorService 时不调用 Thread.interrupt
【发布时间】:2014-04-16 07:21:28
【问题描述】:

当我取消当前正在执行的任务时,我需要调用 MyThread.interrupt()。为什么不是public class Main {

public static void main(String[] args) {
    ExecutorService executor = Executors.newFixedThreadPool(10);
    List<MyThread> threads = new ArrayList<Main.MyThread>();

    List<Future> futureList = new ArrayList<Future>();
    for (int i = 0; i < 30; i++) {
        MyThread myThread = new MyThread(i);
        futureList.add(executor.submit(myThread));
        threads.add(myThread);
    }
    for (Future future : futureList) {
        if (future != null) {
            future.cancel(true);
        }
    }

    // Calling interrupt directly. It works
    for (MyThread myThread : threads) {
        myThread.interrupt();
    }
    shutdownAndAwaitTermination(executor);

}

static void shutdownAndAwaitTermination(ExecutorService pool) {
    pool.shutdown(); // Disable new tasks from being submitted
    try {
        // Wait a while for existing tasks to terminate
        if (!pool.awaitTermination(10, TimeUnit.SECONDS)) {
            pool.shutdownNow(); // Cancel currently executing tasks
            // Wait a while for tasks to respond to being cancelled
            if (!pool.awaitTermination(10, TimeUnit.SECONDS)) System.err.println("Pool did not terminate");
            else System.out.println("Maybe OK");
        } else {
            System.out.println("OK");
        }
    } catch (InterruptedException ie) {
        // (Re-)Cancel if current thread also interrupted
        pool.shutdownNow();
        // Preserve interrupt status
        Thread.currentThread().interrupt();
    }
}

private static class MyThread extends Thread {

    HttpURLConnection connection;

    final int i;

    public MyThread(int i) {
        this.i = i;
    }

    @Override
    public void interrupt() {
        super.interrupt();
        if (connection != null) {
            connection.disconnect();
        }
    }

    @Override
    public void run() {
        // Initialize HttpURLConnection and upload / download data
    }

}

}

【问题讨论】:

    标签: java multithreading threadpool interrupt


    【解决方案1】:

    被调用了,这里改一下看看输出

    ...
                } catch (InterruptedException e) {
                    System.out.println(i + " interrupted");
                    Thread.currentThread().interrupt();
                }
    ...
    

    问题是 ThreadPoolExecutor 使用它自己的线程来运行你的任务,它会中断这个线程而不是你的线程。扩展 Thread 是没有意义的,而是实现 Runnable。如果您仍然要使用 Thread,那么您可以直接从 MyThread.run() 调用 MyThread.interrupt()

    【讨论】:

    • 实际上我在这些线程上下载或上传数据。当我需要停止进程时,在每个下载/上传数据的线程上调用interrupt 并在那里断开连接是合乎逻辑的。所以,我不能只实现Runnable,因为它没有interrupt。我更新了我的问题。
    • 那你可以直接调用你的interrupt()吗?
    • 当然可以。我只是觉得这是多余的。如果您在回答中提到它,我会接受它
    【解决方案2】:

    executor.submit(new MyThread(i)) 有效,因为MyThread 扩展了Thread,它实现了Runnable

    因此,run 方法实际上由您在线程池中启动的 10 个线程之一执行。当取消Future 时,MyThreadinterrupt 方法不会被执行,因为它不是正在执行的线程,而是考虑一个Runnable。尽管如此,由您的池启动的线程的interrupt 会被调用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-22
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 2013-01-29
      • 1970-01-01
      • 2012-11-06
      相关资源
      最近更新 更多