免责声明:这个答案有一个教程字符。
基本方法:我们最初保持简单,不处理Thread.sleep
方法期间的中断。本质上,您应该有一个外部可设置的变量,run 方法在循环的每次迭代中检查该变量;然后您可以将该变量设置为正常终止该run()
方法。请注意这个习语可以很容易地用于 Java 以外的语言。
例如:
public class MyThreadedClass extends Thread {
private volatile boolean completed = false;
public void setCompleted() {
this.completed = true;
}
public void run()
{
while (!completed) {
// do anything you fashion
}
}
public static void main(String... args)
{
MyThreadedClass x = new MyThreadedClass();
MyThreadedClass y = new MyThreadedClass();
x.start();
y.start();
x.setCompleted(); // will complete as soon as the latest iteration finishes
...
}
}
评论: volatile 标志告诉编译器completed
可能(并且将会)在函数控制之外进行更改run()
,即另一个线程可能会更改它。否则循环中的迭代检查可能会根据类的唯一同步行为被错误地优化。
在您的特定run()
情况下,我们利用for
循环,因此我们的方法转化为以下内容:
public void run()
{
try {
for(int i=0;i<20 && !completed;++i) {
Thread.sleep(500);
System.out.print(i +"\n"+ "..");
}
} catch(Exception e) {
e.printStackTrace();
}
}
评论:很明显,由于睡眠呼叫,您可能需要等待长达 500 毫秒。但是,一般来说,如果您的代码必须执行改变变量状态的操作(特别是,如果这些变量在多个线程之间共享!),这样您就不会让这些变量处于不正确的状态。实际上,由于您控制了终止,因此您可以正确处理事务。这显然假设,在循环的每次迭代结束时,变量状态是一致的。
现在让我们改进处理期间中断的基本方法Thread.sleep
。
完整的答案:这个答案涉及到,从调用方来说,该Thread.interrupt()
方法的使用,这使得该方法严格特定于 Java。
public class MyThreadedClass extends Thread {
public void run()
{
try {
for(int i=0;i<20 && !this.isInterrupted();++i) {
Thread.sleep(500);
System.out.print(i +"\n"+ "..");
...
// some molassy slow code here, where you may sprinkle isInterrupted()
// checks and consequent break statements
}
} catch(InterruptedException e) {
// do whatever you need to clean things up
} catch(Exception e) {
// handle other exceptions as seen fit
}
}
public static void main(String... args)
{
MyThreadedClass x = new MyThreadedClass();
x.start();
// will complete
// a) as soon as one isInterrupted() check breaks the loop, or
// b) "immediately" during the blocking call to sleep()
x.interrupt();
...
}
}
评论:在这种情况下,线程本身已经完成了一半的工作。如果你只需要在Thread.sleep
通话过程中打断,那么你不需要做任何事情,除了处理InterruptedException
来清理你的状态,如果有必要的话。相反,如果您需要在“慢”代码期间中断,则必须this.isInterrupted()
在您喜欢的任何地方(可能在多个地方)调用并中断循环;循环条件内的调用很常见但不是必需的。
更多信息可以在 Java 并发中断教程中找到。