使用以下代码时出现异常:我IllegalThreadStateException
已经启动了这个线程一次(通过使用thread.start()
)并再次尝试在另一个地方启动它,所以使用了以下代码:
thread.interrupt();
thread.start();
而是thread.start()
投掷IllegalThreadStateException
。
我应该用什么来解决它?
使用以下代码时出现异常:我IllegalThreadStateException
已经启动了这个线程一次(通过使用thread.start()
)并再次尝试在另一个地方启动它,所以使用了以下代码:
thread.interrupt();
thread.start();
而是thread.start()
投掷IllegalThreadStateException
。
我应该用什么来解决它?
Thread
对象只能启动一次。如果您需要停止/中断 a Thread
,然后想再次启动它,您应该创建一个新实例并调用start()
它:
thread.interrupt(); // if you need to make sure thread's run() method stops ASAP
thread = new MyThreadSubclass();
thread.start();
IllegalThreadStateException - 如果线程已经启动。
我知道你不能再打电话不是 100% 清楚start()
,即使你以前打电话interrupt()
,但这就是它的工作方式。
如果您查看标准 Java 的 API 文档,这个问题就更清楚了。
除了内特的回答。
AnkitRox 在他的评论中说:
谢谢内特。我也在尝试你的方法。但是当时出现的问题是,它为新实例启动了一个新线程,并且之前的线程也在工作。
所以看起来问题是“即使我调用了中断,线程仍在运行”。考虑这个示例(它很丑,但足以展示主要思想):
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()
线程在调用 throw 的方法之一时被阻塞InterruptedException
,则该方法将返回 throwing 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()
,而是使用一些自定义布尔值。