尝试中断正在运行的线程,在本例中为t1,由线程池中的线程执行。
t2是发送中断的那个。
我无法停止正在运行的t1,t1没有得到InterruptedException。
我错过了什么?
Executor exec1 = Executors.newFixedThreadPool(1);
// task to be interrupted
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
System.out.println("starting uninterruptible task 1");
Thread.sleep(4000);
System.out.println("stopping uninterruptible task 1");
} catch (InterruptedException e) {
assertFalse("This line should never be reached.", true);
e.printStackTrace();
}
}
};
final Thread t1 = new Thread(runnable);
// task to send interrupt
Runnable runnable2 = new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
t1.interrupt();
System.out.println("task 2 - Trying to stop task 1");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t2 = new Thread(runnable2);
exec1.execute(t1);
t2.start();
t2.join();
答案 0 :(得分:3)
好像你误解了线程和执行者。您为两个runnable创建两个线程对象,但只启动其中一个(t2),t1传递给Executor在其中运行。但是执行程序不需要提供Thread - 它只需要Runnable实现。 Executor本身是一个线程池(通常,但它不是必需的),它只是在其中创建(和池)线程。它看到你的线程就像Runnable一样简单(这是Thread实现的)。因此,您实际上将中断发送到从未启动过的线程。
如果你真的想让你的代码工作,你应该删除Executor,然后显式启动两个线程。
答案 1 :(得分:3)
您的错误是您尝试在Thread
上执行ThreadPool
。
此出现,因为Thread
碰巧实现了Runnable
,但因为该线程仅用作Runnable
而未启动为一个Thread
,调用#interrupt()
等方法将无法达到预期的效果。
如果您仍然需要使用线程池,则应考虑使用类似FutureTask
的类。将Runnable
包裹在FutureTask
中,然后将任务提交到线程池。然后,当您想要中断任务时,请致电futureTask.cancel(true)
。
答案 2 :(得分:1)
问题是你永远不知道Executor
将使用哪个线程来运行你的任务。
即使您提交了Thread
对象,执行程序也将使用固定线程池创建的线程。因此,引用t1
的线程不是您的任务将在其中执行的线程。所以调用t1.interrupt()
不会做任何事情。
要正确地执行此操作,请使用ExecutorService
并使用submit()
提交Runnable
/ Callable
个对象。这将返回Future
,其中公开了cancel()
方法,该方法可用于取消任务。
答案 3 :(得分:0)
要中断执行程序线程,
final ExecutorService exec1 = Executors.newFixedThreadPool(1);
final Future<?> f = exec1.submit(runnable);
...
f.cancel(true);
答案 4 :(得分:0)
调用Thread.interrupt不一定会抛出InterruptedException。它可能只是设置线程的中断状态,可以通过Thread.interrupted()或Thread.isInterrupted进行轮询。
有关详细信息,请参阅http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Thread.html#interrupt()。