怎么关闭一个 Java 线程 ( Thread ) ? 噢,不,正确的问题是怎么正确的关闭一个 Java 线程?
这个问题是不是很简单? 很简单啊,不就是使用 Thread.stop()
方法么?
但是,根据 ORACLE 的更新文档 ,Thread.stop()
方法可能导致监视器对象被破坏。
因此,我们必须使用其它更安全的方法,或在 Thread.stop()
方法上做一些改变。
使用一个标志 ( Flag )
假设存在一个任务,这个任务并不会自己自动结束,因此我们必须找到一些方式来停止该线程。
为了方便你的理解,我们从创建和启动线程的类开始,一步一步讲解。
首先,我们需要一个原子性的标志 ( flag )
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 来启动/停止执行。
中断线程
当把 sleep()
设置为较长的间隔时,或者我们正在等待可能永远不会被释放的 锁 时会发生什么 ?
我们面临长期阻塞或永不干净的风险。
为了解决这类问题,我们可以创建一个 interrupt()
。
为了演示如何创建 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
异常,就像任何其它阻塞调用一样。
后记
哎,本来可以使用 Thread.stop()
解决的问题,结果为了考虑锁和监视器,整蛊了一个长的解决方案,这难道就是 Java 开发不能避免的?
最新评论
徒弟可以A师傅,学生可以A老师,为什么外包不能A正式,我觉得很正常。异性相吸这是宇宙真理
PHP天下第一(狗头叼花)
第一个不需要关注公主号直接给激活码的帖子!
客户端超时断开后,服务端如果没有设置超时机制,那也会继续等待处理,万一这期间有消息到了,那不是就接受到消息处理了,但是也没有办法返回到客户端,导致消息丢失。
企业级GO项目开发实战 Kubernetes权威指南 第六版
https://pan.baidu.com/s/1q3bnTncIACKoTZFxvx7BQw?pwd=ii7n
RabbitMQ精讲,项目驱动落地,分布式事务拔高 有吗?
Spring Cloud Alibaba 微服务架构实战 https://pan.baidu.com/s/1jF5voFRoeF0lYAzAPBWSbw?pwd=chqk