5

我想在固定的时间后中断一个线程。其他人问了同样的问题,投票最多的答案(https://stackoverflow.com/a/2275596/1310503)给出了下面的解决方案,我稍微缩短了。

import java.util.Arrays;
import java.util.concurrent.*;

public class Test {
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.invokeAll(Arrays.asList(new Task()), 2, TimeUnit.SECONDS);
        executor.shutdown();
    }
}

class Task implements Callable<String> {
    public String call() throws Exception {
        try {
            System.out.println("Started..");
            Thread.sleep(4000); // Just to demo a long running task of 4 seconds.
            System.out.println("Finished!");
        } catch (InterruptedException e) {
            System.out.println("Terminated!");
        }
        return null;
    }
}

他们补充说:

sleep() 不是必需的。它仅用于 SSCCE/演示目的。只需在此处代替 sleep() 执行您的长时间运行的任务。

但是如果你替换Thread.sleep(4000);for (int i = 0; i < 5E8; i++) {}then 它不会编译,因为空循环不会抛出 InterruptedException。为了使线程可中断,它需要抛出一个 InterruptedException。

有什么方法可以使上述代码与一般的长时间运行的任务一起工作,而不是sleep()

4

4 回答 4

5

如果您希望您的操作是可中断的(即应该可以在它完成之前中断它),您需要使用其他可中断操作(Thread.sleep、InputStream.read、阅读更多信息)或手动检查线程中断状态使用 Thread.isInterrupted 的循环条件。

于 2012-04-05T15:40:23.403 回答
4

您可以检查线程的中断状态,例如:

public static void main(String[] args) throws Exception {
    ExecutorService executor = Executors.newSingleThreadExecutor();
    executor.invokeAll(Arrays.asList(new Task()), 2, TimeUnit.SECONDS);
    executor.shutdown();
}

static class Task implements Callable<String> {

    public String call() throws Exception {
        System.out.println("Started..");
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            if (Thread.currentThread().isInterrupted()) {
                System.out.println("Interrupted!");
                return null;
            }
        }
        System.out.println("Finished!");
        return null;
    }
}
于 2012-04-05T15:42:56.427 回答
3

你误会了。

“...为了使线程可中断,它需要抛出一个 InterruptedException”根本不正确。那个 catch 块的存在只是因为Thread.sleep()方法 throws InterruptedException。如果您没有使用 sleep (或任何其他可以 throw 的代码InterruptedException),那么您不需要 catch 块。

于 2012-04-05T15:38:00.643 回答
-2

InterruptedException如果您替换sleep. 您应该删除 try-catch InterruptedException

public String call() {
    System.out.println("Started..");
    for (int i = 0; i < 5E8; i++) {}
    System.out.println("Finished!");
    return null;
} 
于 2012-04-05T15:48:39.050 回答