java 线程 杀掉_java如何合理的停掉一个线程

Java中stop方法不安全,可能导致数据完整性问题。推荐使用interrupt方法配合循环条件来安全退出线程。在循环中检查isInterrupted状态并捕获InterruptedException,确保线程优雅退出。当线程同步时,可以使用volatile关键字保证变量可见性,防止因工作内存未更新导致的死循环。
摘要由CSDN通过智能技术生成

首先如果我们问java如何去停掉一个线程,大家肯定会说stop嘛,但是也有一些朋友提出质疑,stop安全吗?

没错stop是不提倡的,

不提倡的stop()方法

臭名昭著的stop()停止线程的方法已不提倡使用了,原因是什么呢?

当在一个线程对象上调用stop()方法时,这个线程对象所运行的线程就会立即停止,并抛出特殊的ThreadDeath()异常。这里的“立即”因为太“立即”了,

假如一个线程正在执行:

synchronized void {

x = 3;

y = 4;

}

由于方法是同步的,多个线程访问时总能保证x,y被同时赋值,而如果一个线程正在执行到x = 3;时,被调用了 stop()方法,即使在同步块中,它也干脆地stop了,这样就产生了不完整的残废数据。而多线程编程中最最基础的条件要保证数据的完整性,所以请忘记 线程的stop方法,以后我们再也不要说“停止线程”了。

如何才能“结束”一个线程?

那么什么方式才是我们提倡的呢,用interrupt()?

那么如何能确保线程真正停止?在线程同步的时候我们有一个叫“二次惰性检测”(double check),能在提高效率的基础上又确保线程真正中同步控制中。那么我把线程正确退出的方法称为“双重安全退出”,即不以isInterrupted ()为循环条件。而以一个标记作为循环条件:

package org.leadfar;

public class MyThread04 extends Thread {

private boolean stop = false;

public MyThread04(String threadName) {

super(threadName);

}

@Override

public void run() {

for (int j = 0; j 

if(this.isInterrupted()) break;

System.out.println(Thread.currentThread().getName()+":"+j);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

public void setStop() {

this.stop = true;

}

//第一个线程

public static void main(String[] args) {

MyThread04 t = new MyThread04("辅线程");

t.start();

for (int i = 0; i 

System.out.println(Thread.currentThread().getName()+":"+i);

}

System.out.println("....................");

t.interrupt();

}

}

但这个很可能不会终止线程,因为当我们终止这个线程时很可能就会发生InterruptedException异常,当有这个异常发生时我们设置的终断状态也会被清除,所以我们要终断某个线程应采用以下这个方法:

package org.leadfar;

public class MyThread04 extends Thread {

private boolean stop = false;

public MyThread04(String threadName) {

super(threadName);

}

@Override

public void run() {

for (int j = 0; j 

if(stop) break;

System.out.println(Thread.currentThread().getName()+":"+j);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

public void setStop() {

this.stop = true;

}

//第一个线程

public static void main(String[] args) {

MyThread04 t = new MyThread04("辅线程");

t.start();

for (int i = 0; i 

System.out.println(Thread.currentThread().getName()+":"+i);

}

System.out.println("....................");

t.setStop();

}

}

通过设置一个我们自己的标识来达到终端某个线程。

讲到这里大家一定就认为这样一定没有问题了对吗,答案是不,

其实大家可以想想我们设置的那个stop变量一定会很老实的被我们修改吗,想想一个简单的例子

这段代码是很典型的一段代码,很多人在中断线程时可能都会采用这种标记办法。但是事实上,这段代码会完全运行正确么?即一定会将线程中断么?不一定,也许在大多数时候,这个代码能够把线程中断,但是也有可能会导致无法中断线程(虽然这个可能性很小,但是只要一旦发生这种情况就会造成死循环了)。

下面解释一下这段代码为何有可能导致无法中断线程。在前面已经解释过,每个线程在运行过程中都有自己的工作内存,那么线程1在运行的时候,会将stop变量的值拷贝一份放在自己的工作内存当中。

那么当线程2更改了stop变量的值之后,但是还没来得及写入主存当中,线程2转去做其他事情了,那么线程1由于不知道线程2对stop变量的更改,因此还会一直循环下去。

所以在这里我们引入了一个关键字volatile,其实这里还有一些java的其他概念原子性,可见性,有序性,有兴趣的朋友可以了解一下

以及volatile

好的那么我们的线程到底怎么才能被我们停掉,相比大家也能感觉到我们可以在stop关键词上加上volatile关键字啊,没错就是这样的方式。其实我们在终止线程的时候有很多复杂的情况,这里就不一一列举了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值