因此使用stop我们在不知道线程到底运行到了什么地方,暴力的中断了线程,如果sleep后的代码是资源释放、重要业务逻辑等比较重要的代码的话,亦或是其他线程依赖t1线程的运行结果,那直接中断将可能造成很严重的后果。
那么不建议使用stop中断线程我们应该怎么去优雅的结束一个线程呢,我们可以存java开发者的注释中窥探到一种解决方案:
可以看到java开发者推荐我们使用以下两种方法来优雅的停止线程。
1.定义一个变量,由目标线程去不断的检查变量的状态,当变量达到某个状态时停止线程。
代码举例如下:
volatile static boolean flag=false;
public static void main(String[] args) throws InterruptedException {
Object o1=new Object();
Thread t1=new Thread(()->{
synchronized (o1)
{
try {
System.out.println(“t1获取到锁”);
while (!flag)
Thread.sleep(5000);//执行业务逻辑
System.out.println(“t1结束”);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
Thread.sleep(1000);
Thread t2=new Thread(()->{
synchronized (o1)
{
try {
System.out.println(“t2获取到锁”);
Thread.sleep(5000);//执行业务逻辑
System.out.println(“t2结束”);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t2.start();
flag=true;
}
运行结果:
2.使用interrupt方法中断线程。
代码举例如下:
public static void main(String[] args) throws InterruptedException {
Object o1=new Object();
Thread t1=new Thread(()->{
synchronized (o1)
{
System.out.println(“t1获取到锁”);
while (!Thread.currentThread().isInterrupted()) {
for (int i = 0; i < 100; i++) {
if(i==50)
System.out.println();
System.out.print(i+" ");
}
System.out.println();
}
System.out.println(“t1结束”);
}
});
t1.start();
Thread t2=new Thread(()->{
synchronized (o1)
{
try {
System.out.println(“t2获取到锁”);
Thread.sleep(5000);//执行业务逻辑
System.out.println(“t2结束”);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t2.start();
t1.interrupt();
}
运行结果:
我们用while (!Thread.currentThread().isInterrupted())来不断判断当前线程是否被中断,中断的话则让线程自然消亡并释放锁。可以看到调用interrupt方法后并不会像stop那样暴力的中断线程,会等到当前运行的逻辑结束后再检查是否中断,非常的优雅。
注:运行举例代码可能不会打印出数字,这是因为t1线程运行到while(!Thread.currentThread().isInterrupted())时,主线程已经调了interrupt方法,因此多次运行可能会打印出数字。
二、suspend的落幕
suspend方法的作用是挂起某个线程直到调用resume方法来恢复该线程,但是调用了suspend方法后并不会释放被挂起线程获取到的锁,正因如此就给suspend和resume这哥俩贴上了容易引发死锁的标签,当然这也正是导致suspend和resume退出历史舞台的罪魁祸首。同样我们看看java开发者为suspend的淘汰给出的理由:
This method has been deprecated, as it is inherently deadlock-prone. If the target thread holds a lock on the monitor protecting a critical system resource when it is suspended, no thread can access this resource until the target thread is resumed. If the thread that would resume the target thread attempts to lock this monitor prior to calling resume, deadlock results. Such deadlocks typically manifest themselves as “frozen” processes.
从中我们可以得出以下结论:
接下来模拟一下由suspend引起的死锁场景,Talk is cheap,show my code:
public static void main(String[] args) throws InterruptedException {
Object o1=new Object();
Object o2=new Object();
Thread t1=new Thread(()->{
synchronized (o1)
{
System.out.println(“t1获取到o1锁开始执行”);
try {
Thread.sleep(5000);//模拟执行业务逻辑
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(“t1执行结束”);
}
});
t1.start();
Thread t2=new Thread(()->{
synchronized (o2)
{
System.out.println(“t2获取到o2开始执行”);
try {
Thread.sleep(2000);//执行耗时业务
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (o1)
{
System.out.println(“t2获取到o1锁开始继续执行”);
}
System.out.println(“t2执行结束”);
}
});
t2.start();
Thread.sleep(1000);
t1.suspend();
//假设抛出了一个未知异常
int i=1/0;
t1.resume();
}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)