“你好,阿米戈!你必须承认,艾莉的 Cancel(取消)想法很棒。”

“是的。”

“实际上,Thread 类中存在一些类似的功能。只是变量不叫 isCancel。而被称为 isInterrupt。并且,用于停止线程的方法不是 cancel(),而是 interrupt()。”

“真的吗?”

“是的。我们来看一下:”

代码 说明
class Clock implements Runnable
{
public void run()
{
Thread current = Thread.currentThread();

while (!current.isInterrupted())
{
Thread.sleep(1000);
System.out.println("Tick");
}
}
}
由于多个线程可以在同一 Clock 对象上调用 run 方法,因此我们为当前线程获取 Thread 对象

只要当前线程的 isInterrupt 变量为 false,Clock 类会每隔一秒向控制台写入一次词语“嘀嘀”。

isInterrupt 变为 true 时,run 方法终止。

public static void main(String[] args)
{
Clock clock = new Clock();
Thread clockThread = new Thread(clock);
clockThread.start();

Thread.sleep(10000);
clockThread.interrupt();
}
主线程启动应始终运行的子线程 (clock)。

等待 10 秒,然后通过调用 interrupt 方法取消任务。

主线程完成工作。

clock 线程结束工作。

而且,人们特别喜欢在 run 方法的无限循环中使用的 sleep 方法会自动检查 isInterrupt 变量。如果一个线程调用 sleep 方法,它将首先为该线程检查 isInterrupt 是否为 true。如果为 true,则方法不会进入休眠状态。相反,它会抛出一个 InterruptedException 异常。

“为什么会抛出异常?直接在循环中使用 isInterrupted() 而不是 isCancel() 会不会更好?”

首先run 方法并不总是包含循环。该方法可能只包含对其他方法的几十个调用。然后,你将必须在每个方法调用之前添加 isInterrupted 检查。”

其次,某个包含许多不同操作的方法可能需要很长时间才能执行完。”

第三,抛出异常不会替代 isInterrupted 检查。这只是一个方便的附加功能。抛出的异常允许你快速将调用堆栈回退到 run 方法本身。”

第四,sleep 方法的使用非常频繁。事实证明,这个有用的方法通过同样有用的隐式检查得到了增强。就像无人明确添加检查,但它确实存在。当你使用别人的代码而自己无法添加检查时,这是非常有用的。”

第五,附加检查不会降低性能。调用 sleep 方法意味着线程不会做任何事情(除了休眠),因此额外的工作不会困扰任何人。”

“那会引发激烈的争论。”

最后一点是:你的 run 方法可以调用别人的代码 — 你无权访问的代码(源代码和/或更改代码的权限)。它可能没有 isInterrupted 检查,并且可能使用‘try ... catch (Exception e)’来捕获所有异常。”

没有人可以保证线程将被停止。线程只能自行停止