java 停止 code_Java:一个停止线程的方法——interrupt

一、前言

之前本人写了一篇防止Controller中的线程被重复调用的文章,大概代码如下:

//sonarqube检查要求static变量必须是final,为避开检查,使用final HashMap

public final static HashMap threadMap = new HashMap<>();

--------------------------------------------------

Thread nowThread = threadMap.get("nowThread");

if(nowThread != null && nowThread.isAlive()){

LOG.info("当前存在正在执行的线程,本次线程不执行,请稍后再试");

return;

}

else{

threadMap.put("nowThread",Thread.currentThread());

}

//主要代码省略

......

//线程执行完毕,置空

threadMap.put("nowThread",null);

后来,由于担心这个线程会卡死,导致后续正常调用该线程的操作无法进行,因此加了个手动停止线程运行的方法(interrupt):

//传入一个type参数,如果为3,中断上一个线程的执行

if(type == 3){

try{

Thread nowThread = threadMap.get("nowThread");

//中断上一个线程

nowThread.interrupt();

threadMap.put("nowThread",null);

String backMsg = "线程interrupt成功!";

LOG.info(backMsg);

return;

}catch(Exception e){

threadMap.put("nowThread",null);

String backMsg = "线程interrupt失败,只将map置空!";

LOG.error(backMsg,e);

return;

}

}

然而,仅仅这样并不能停止线程运行。

二、停止线程运行的方法

使用标志位停止线程,还行,但是遇到sleep时的线程就无法停止了,必须等线程sleep结束、运行到判断标志位步骤时才行。

使用stop()停止线程,不安全,已不推荐使用。会立即停止线程运行,会使一些清理性的工作的得不到完成,如文件,数据库等的关闭;会立即释放该线程所持有的所有的锁,导致数据得不到同步,出现数据不一致的问题。

使用interrupt()中断线程,需要配合代码逻辑实现停止线程。

需要注意,调用 interrupt() 方法仅仅是在当前线程中打一个停止的标记,并不是真的停止线程;如果直接将线程停止,就会和stop一样出现问题。

因此还需要配合代码逻辑实现。

三、正确使用interrupt停止线程运行

先看下例子:

public static void main(String[] args) throws InterruptedException{

Thread t1 = new Thread(){

@Override

public void run(){

//一个循环线程

while(true){

//一种结束情况

if(this.currentThread().isInterrupted()){

System.out.println("线程被打断,停止运行");

break;

}else{

System.out.println("线程在运行");

try{

//Thread.sleep(0L);

Thread.sleep(1000L);

}catch(InterruptedException e){

//另一种结束情况

System.out.println("线程睡眠时被打断,停止运行");

break;

}

}

}

}

};

t1.start();

Thread.sleep(5000L);

t1.interrupt();

System.out.println("主线程打断t1完成");

}

上方的代码中,先启动一个线程,然后主线程在5秒后打断它,它有两种停止情况:

执行if判断时,发现标志位为true,因此执行break,之后停止运行。

线程还在sleep,此时发现被打断,会抛出InterruptedException,然后被catch到,执行break,之后停止运行。

结合实际代码,如果线程中不需要sleep,则判断isInterrupted()即可;

如果线程中存在sleep,则catch中使用break、return之类的停止线程即可;

当然也可以两种都写。

本人的代码中有sleep,因此只在catch中加了break,没有判断标志位。

四、总结

使用interrupt停止线程比标志位停止线程的好处在于,它不仅能通过标志判断是否要停止线程,而且当线程处于sleep状态时,使用interrupt就可以停止线程,而标志位不行。

使用interrupt停止线程比stop停止线程的好处在于,stop不安全,会产生难以预料的后果,而interrupt不会。

停止线程时,不仅要直接调用interrupt(),还要写好相应的代码逻辑,一种逻辑与标志位停止线程类似,另一种逻辑要注意在try中写Thread.sleep(当你的线程需要sleep时),在catch中写break、return之类的方法。

PS:之前写sleep时,都是这么写的:

try{

Thread.sleep(5000L);

}catch(Exception e){}

现在终于知道应该怎么写了……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值