停止线程是比较重要的一个技术点,但是如果用不好可能会导致程序出现超出预期的效果,并且很难定位错误。
停止线程可以使用interrupt()和stop(),下面分别讨论两种方式
一、interrupt()
interrupt()用来停止线程,但是这个方法不能停止一个正在运行的线程,只是打了一个停止的标记,并不是真的停止了线程。
但是如果线程正处于sleep()状态,如果你打断了,会抛出java.lang.InterruptedException: sleep interrupted
看下面这段代码:
public class MyThread extends Thread{ @Override public void run(){ for(int i=0;i<100000;i++){ System.out.println("i="+ i); } } public static void main(String[] args) { try { MyThread myThread = new MyThread(); myThread.start(); Thread.sleep(100); myThread.interrupt(); } catch (Exception e) { e.printStackTrace(); } } }
线程run()中是for循环,查看执行结果会发现打印出来的日志是10万条,并没有少,证明 interrupt()方法并没有停止线程,那么到底怎么能停止线程呢?刚才说到interrupt()方法是并没有停止线程,而是打了一个停止标记,那么解决办法就是执行了interrupt()方法后判断线程是否处于停止状态,如果有停止标记则是停止状态,自己用代码方式停止,那么先来介绍一下判断线程停止状态的方法,有两种
判断线程停止状态:
1、this.interrupted():判断当前线程是否是中断状态,执行后将中断状态标志清除为false,意思是这个执行了一遍后再执行一遍结果会返回false
2、this.isInterrupted():判断线程Thread对象是否是中断状态,但不清除状态标志
知道了两种判断方法接下来看下怎么停止线程
public class MyThread extends Thread{ @Override public void run(){ for(int i=0;i<100000;i++){ System.out.println("i="+ i); if(this.isInterrupted()){ System.out.println("线程现在属于停止状态,我要结束了"); break; } } System.out.println("线程结束了"); } public static void main(String[] args) { try { MyThread myThread = new MyThread(); myThread.start(); Thread.sleep(100); myThread.interrupt(); } catch (Exception e) { e.printStackTrace(); } } }
运行结果:
...
i=12927 i=12928 i=12929 i=12930 i=12931 i=12932 线程现在属于停止状态,我要结束了 线程结束了
从结果上看,for循环到12932次的时候结束了,在线程调用了interrupt()方法后,在线程中判断到线程现在处于想要停止的状态,for循环使用break停止了线程,完美!但是break只是打断了for循环,所有后面那句“线程结束了”还是执行了。如果想要让下面的“线程结束了”不执行有种方式有两种:
第一种:是把break换成throws new Exception(),然后再捕获异常就行了。然后在异常中处理想处理的逻辑。
第二种:是把break换成return,也能结束线程。
一般这种突然停止了还是做相关处理吧,建议使用抛异常方式
二、stop()
强行终止当前线程,不安全,已经作废的方法(这是一种暴力停止)。强制让线程停止可能使一些清理工作得不到完成。另外一种情况就是对锁定的对象进行了“解锁”,导致数据得不到同步的处理,出现数据不一致的情况。最终导致程序执行的流程错误。
还有stop()可能会抛出java.lang.ThreadDeath异常,此异常通常情况下不用显示的捕获
三、suspend()与resume()
暂定线程,意味着可以恢复运行,在Java多线程中可以使用suspend()方法暂停线程,使用resume()方法恢复线程。
这两个方法已经废弃使用。
缺点:独占:使用这俩个方法如果使用不当,极容易造成公共的同步对象独占,使得其他线程无法访问公共对象。
不同步:使用这两个方法也容易出现因为线程的暂停而导致数据不同步的情况。