1.简介
在这篇简短的文章中,我们将介绍如何在Java中停止一个Thread - 这不是那么简单,因为不推荐使用Thread.stop()方法。
如Oracle在更新中所述, stop()可能导致受监视的对象被破坏。
2.使用标志
让我们从创建和启动线程的类开始。这个任务不会自行结束,所以我们需要一些方法来停止该线程。
我们将使用原子标志:
public class ControlSubThread implements Runnable {
private Thread worker;
private final AtomicBoolean running = new AtomicBoolean(false);
private int interval;
public ControlSubThread(int sleepInterval) {
interval = sleepInterval;
}
public void start() {
worker = new Thread(this);
worker.start();
}
public void stop() {
running.set(false);
}
public void run() {
running.set(true);
while (running.get()) {
try {
Thread.sleep(interval);
} catch (InterruptedException e){
Thread.currentThread().interrupt();
System.out.println(
"Thread was interrupted, Failed to complete operation");
}
// do something here
}
}
}
我们使用AtomicBoolean而不是让while循环判断常量true,现在我们可以通过将其设置为true / false来启动/停止执行。
正如我们对Atomic Variables的介绍中所解释的那样,使用AtomicBoolean可以防止在设置和检查来自不同线程的变量时发生冲突。
3.中断线程
当sleep()设置为较长的间隔时,或者我们正在等待可能永远不会释放的锁时会发生什么?
我们面临长期封锁或永不干净的风险。
我们可以为这些情况创建interrupt(),让我们为类添加一些方法和一个新标志:
public class ControlSubThread implements Runnable {
private Thread worker;
private AtomicBoolean running = new AtomicBoolean(false);
private int interval;
// ...
public void interrupt() {
running.set(false);
worker.interrupt();
}
boolean isRunning() {
return running.get();
}
boolean isStopped() {
return stopped.get();
}
public void run() {
running.set(true);
while (running.get()) {
try {
Thread.sleep(interval);
} catch (InterruptedException e){
Thread.currentThread().interrupt();
System.out.println(
"Thread was interrupted, Failed to complete operation");
}
// do something
}
}
}
我们添加了一个interrupt()方法,它将我们的运行标志设置为false并调用工作线程的interrupt()方法。
如果线程在调用此函数时处于休眠状态,则sleep()将以InterruptedException退出,就像任何其他阻塞调用一样。
这会将线程返回到循环,并且它将退出,因为running是false。
4 结论
在这个快速教程中,我们研究了如何使用原子变量(可选择结合对interrupt()的调用)来干净地关闭线程。这绝对比调用已弃用的stop()方法并永远存在锁定和内存损坏更可取。
关注公众号:「Java知己」,每天更新Java知识哦,期待你的到来!
- 发送「1024」,免费领取 30 本经典编程书籍。
- 发送「Group」,与 10 万程序员一起进步。
- 发送「JavaEE实战」,领取《JavaEE实战》系列视频教程。
- 发送「玩转算法」,领取《玩转算法》系列视频教程。