我正在编写一个包含循环的线程程序,该循环休眠30秒并且循环执行,直到在线程中执行的runnable对象上将“shutdown”标志设置为true。
class MyThread extends Thread{
//set this to true to stop the thread
volatile boolean shutdown = false;
public void stopMe() {
shutdown=true;
}
public void run () {
while (!shutdown) {
// continue processing
try {
Thread.sleep(30000);
} catch (InterruptedException e) {}
}
}
}
但是当shutdown标志设置为true时,线程会立即退出吗?如果它在睡眠呼叫中怎么办?如何通过另一个线程立即唤醒线程?在学习线程时,请帮助我们获得这些问题的答案
答案 0 :(得分:2)
当线程的run方法结束时,线程也会结束。
要回答您的第二个问题,您必须注意睡眠部分。
JLS 17.3。睡眠和产量
重要的是要注意Thread.sleep和Thread.yield都没有 有任何同步语义。特别是编译器 不必将寄存器中缓存的写入刷新到共享内存 在调用Thread.sleep或Thread.yield之前,编译器也没有 在调用Thread.sleep之后,必须重新加载缓存在寄存器中的值 或Thread.yield。
例如,在下面(破碎的)代码片段中,假设 this.done是一个非易失性布尔字段:
while (!this.done)
Thread.sleep(1000);
编译器可以自由阅读this.done字段一次,并重用 每次执行循环时的缓存值。这意味着 循环永远不会终止,即使另一个线程改变了 this.done的价值。
请注意,在您的情况下,它是正确的,因为您的标志是易失性的,这只是一个警告。
至于你的最终请求,你可以使用Thread#interrupt
唤醒一个睡眠线程。请注意,中断睡眠线程将抛出InterruptedException
,因此请务必处理它。
答案 1 :(得分:0)
在调用Thread.sleep()
期间,线程可能会被中断。您必须在代码中捕获该异常。因此,如果您想要在等待时停止您的线程,您必须执行以下操作:
MyThread myThread = new MyThread();
myThread.run();
//some time later we want to stop myThread
myThread.stopMe(); //sets the flag
myThread.interrupt(); //wakes the thread up if it is sleeping
myThread.join(); //wait for myThread to finish
答案 2 :(得分:0)
虽然简单Thread.interrupt()
回答了原始问题,但这个解决方案并没有很好地扩展到线程在不睡觉时做一些真实的东西。在这种情况下,在错误的时刻传递的中断可能会被我们无法控制的代码错误处理。 (它不应该,但是当发生这种情况时,我看到了一些现实生活中的例子。)
所以我实际上会“滥用”锁来实现“可中断的睡眠”
class MyThread extends Thread {
private final Object sleepLock = new Object();
//set this to true to stop the thread
boolean shutdown = false;
public void stopMe() {
synchronized (sleepLock) {
shutdown = true;
sleepLock.notifyAll();
}
}
private void sleepCancellably(long millis) throws InterruptedException {
long sleepEnd = System.currentTimeMillis() + millis;
synchronized (sleepLock) {
while (!shutdown) {
long remaning = sleepEnd - System.currentTimeMillis();
if (remaining <= 0) {
break;
}
sleepLock.wait(remainig);
}
}
}
public void run () {
while (!shutdown) {
// when doing some important stuff, stopMe() want interrupt us
doSomeImportantStuff();
// continue processing
try {
sleepCancellably(30000);
} catch (InterruptedException e) {
// not expected. log.errror(e) or e.printStackTrace()
}
}
}
}