使用以下代码时出现IllegalThreadStateException
异常:
我已经开始使用此线程一次(使用thread.start()
)并再次尝试在其他位置启动它,因此使用以下代码:
thread.interrupt();
thread.start();
但thread.start()
正在投掷IllegalThreadStateException
。
我应该用什么来解决它?
答案 0 :(得分:18)
Thread
个对象只能启动一次。如果您需要停止/中断Thread
,然后又要重新启动它,则应创建一个新实例,并在其上调用start()
:
thread.interrupt(); // if you need to make sure thread's run() method stops ASAP
thread = new MyThreadSubclass();
thread.start();
IllegalThreadStateException - 如果线程已经启动。
我知道,即使您之前曾致电start()
,也无法再次致电interrupt()
,但这就是它的工作方式。
如果你看一下API docs for standard Java,这个问题会更清楚。
答案 1 :(得分:8)
除了Nate的回答。
AnkitRox在评论中指出:
谢谢Nate。我也在尝试你的方法。但是当时发生的问题是,它为新实例启动了一个新线程,之前的线程也在运行。
所以看起来问题是“线程仍在运行,即使我在其上调用了中断”。考虑这个样本(它很难看,但足以显示主要想法):
final Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
for (int i = 0; i < 100000000; i++); // simulate some action
System.out.println("hi, interrupted = "
+ Thread.currentThread().isInterrupted());
}
}
});
t.start();
new Timer(true).schedule(
new TimerTask() {
public void run() {
t.interrupt();
}
},
1000 // 1 second delay
);
注意,即使在调用interrupt()
之后,线程仍继续运行。产生的输出是:
hi, interrupted = false
hi, interrupted = true
hi, interrupted = true
hi, interrupted = true
...
hi, interrupted = true
实际上,除非有力地关闭,否则程序永远不会停止。那么interrupt()
呢?它只是将中断标志设置为true
。调用interrupt()
后,Thread.currentThread().isInterrupted()
开始返回false
。这就是全部。
另一种情况是,如果在调用其中一个抛出interrupt()
的方法时阻塞线程,则调用InterruptedException
,那么该方法将返回抛出InterruptedException
。如果线程的代码只是“吃掉”那个异常,那么线程仍将继续运行,考虑一个样本:
final Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
System.out.println("hi, interrupted = "
+ Thread.currentThread().isInterrupted());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println("got InterruptedException");
}
}
}
});
t.start();
new Timer(true).schedule(
new TimerTask() {
public void run() {
t.interrupt();
}
},
1000 // 1 second delay
);
注意,即使在调用interrupt()
之后,线程仍继续运行。产生的输出是:
hi, interrupted = false
got InterruptedException
hi, interrupted = false
hi, interrupted = false
...
hi, interrupted = false
注意,即使在interrupted = false
被调用之后,这次interrupt()
也是如此。这是因为无论何时捕获InterruptedException
,中断的标记都会重置为false
。
在Java中停止线程是合作机制。意味着没有线程本身的合作就无法完成。以下是上述示例的固定版本:
final Thread t = new Thread(new Runnable() {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("hi, interrupted = "
+ Thread.currentThread().isInterrupted());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println("we've been interrupted");
// restore the interrupted flag
Thread.currentThread().interrupt();
}
}
}
});
t.start();
new Timer(true).schedule(
new TimerTask() {
public void run() {
t.interrupt();
}
},
1000 // 1 second delay
);
因此,正确的方法应该是定期检查中断标志。如果检测到中断状态,则尽快返回。另一个常见选项是根本不使用Thread.interrupt()
,而是使用some custom boolean instead。