在Java中有以下3种方法可以终止一个正在运行的线程:
1、使用退出标志,是线程正常退出,也就是run方法完成后线程终止。
2、使用stop方法强制终止线程,蛋不推荐使用这个方法,因为stop、suspend和resume一样,都是作废过期的方法。
3、使用interrupt方法中断线程,大多数停止一个线程使用Thread.interrupt()方法,但是这个方法不会终止一个正在运行的线程,还需要加入一些判断才可以完成线程的停止。 下面我就用几个例子来介绍一下各种停止线程的效果。 一、停不了的线程——interrupt 本例子将调用interrupt()方法来停止线程,但是效果并不理想,并不能停止正在运行的线程,因为调用interrupt()方法仅仅是在当前线程中打了一个停止的标记,并不能真的停止线程。
public static void main(String[] args) { MyThread1 t = new MyThread1(); t.start(); try { Thread.sleep(2); Thread.interrupted(); } catch (InterruptedException e) { System.out.println("main catch"); e.printStackTrace(); } } public static class MyThread1 extends Thread { @Override public void run() { super.run(); for (int i = 0; i < 5000; i++) { System.out.println("i=" + (i + 1)); } } }
运行结果我值截取了最后一段,控制台上正好输出到5000,说明调用interrupt方法并没有停止线程,运行结果如下:
那么怎么才能停止线程呢?下面我回来介绍。
二、能停止的线程——异常法
先看一个例子:
public static void main(String[] args) throws InterruptedException { MyThread t = new MyThread(); t.start(); Thread.sleep(50); t.interrupt(); System.out.println("end"); } public static class MyThread extends Thread { @Override public void run() { // TODO Auto-generated method stub super.run(); for (int i = 0; i < 5000; i++) { if (this.interrupted()) { System.out.println("已经是停止状态了!我要退出了!"); break; } System.out.println("i=" + (i + 1)); } System.out.println("如果我被输出了,说明run方法还在继续执行,线程并未停止!"); } }
输出结果如下:
从上面的结果可以看出来,这样写只是把for循环结束了,但是下面接着输出了“如果我被输出了,说明run方法还在继续执行,线程并未停止!”这句话,说明这样写并不能让run方法停止,所以这样写不可行。下面再来看一个例子。
public static void main(String[] args) throws InterruptedException { MyThread t = new MyThread(); t.start(); Thread.sleep(50); t.interrupt(); System.out.println("end"); } public static class MyThread extends Thread { @Override public void run() { super.run(); try { for (int i = 0; i < 5000; i++) { if (this.interrupted()) { System.out.println("已经是停止状态了!我要退出了!"); //异常法结束线程 throw new InterruptedException(); } System.out.println("i=" + (i + 1)); } System.out.println("我在for下面"); } catch (InterruptedException e) { System.out.println("进入Thread线程的run方法中的catch!"); e.printStackTrace(); } } }
下面来看一下控制台上的输出结果:
来分析一下结果,throw new InterruptedException()这句话下面的内容已经不会再执行了,因为“我在for下面”这句话并没有输出来,而是进入了catch,结束了整个run方法。所以异常方法来停止线程方法是靠谱的。
三、在沉睡中停止线程
public static void main(String[] args) { try { MyThread t = new MyThread(); t.start(); Thread.sleep(200); t.interrupt(); } catch (Exception e) { System.out.println("main catch"); e.printStackTrace(); } System.out.println("end!"); } public static class MyThread extends Thread { @Override public void run() { super.run(); try { System.out.println("run begin"); //为了确保能停止线程,这个休眠时间尽量长一点,如果时间太短,有可能主线程还没休眠结束呢,子线程就休眠结束了,这个线程也就正常运行了。 sleep(2000); System.out.println("run end"); } catch (Exception e) { System.out.println("在沉睡中被停止!进去catch!" + this.isInterrupted()); e.printStackTrace(); } } }
运行结果如下:
来分析一下结果,"run end"这句话没有输出,说明子线程里的sleep下面的内容再也不会执行了,而是进入到catch里面了,从而停止了run方法。说明这样写也是靠谱的。
四、能停止的线程——暴力停止
使用stop()方法停止线程是非常暴力的行为,并且使用stop()方法会导致运行结果不一样,已经被官方文档废弃使用了。下面我来展示一个例子。
public static void main(String[] args) { MyThread t = new MyThread(); t.start(); try { Thread.sleep(9000); t.stop(); } catch (Exception e) { e.printStackTrace(); } } public static class MyThread extends Thread { private int i = 0; @Override public void run() { super.run(); while (true) { i++; System.out.println("i=" + i); try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
五、使用return停止线程
将interrupt()和return结合也能实现停止线程的效果。但是建议使用抛异常停止线程,因为可以处理发生异常时候的相关信息。下面看一段代码。
public static void main(String[] args) throws InterruptedException { MyThread t = new MyThread(); t.start(); Thread.sleep(2); t.interrupt(); } public static class MyThread extends Thread { @Override public void run() { super.run(); for (int i = 0; i < 5000; i++) { if (this.interrupted()) { System.out.println("已经是停止状态了!我要退出了!"); return; } System.out.println("i=" + (i + 1)); } } }
下面看一下运行结果:
六、暂停线程
暂停线程异味着此线程还可以恢复运行,在java中使用suspend()方法暂停线程,使用resume()方法恢复线程。下面看一段代码。
public static void main(String[] args) throws InterruptedException { MyThread t = new MyThread(); t.start(); //A段 暂停线程 t.suspend(); System.out.println("A="+System.currentTimeMillis() +"\t"+"i="+t.getI()); Thread.sleep(500); System.out.println("A="+System.currentTimeMillis() +"\t"+"i="+t.getI()); //B段 继续恢复 t.resume(); System.out.println("B="+System.currentTimeMillis() +"\t"+"i="+t.getI()); Thread.sleep(500); System.out.println("B="+System.currentTimeMillis() +"\t"+"i="+t.getI()); //C段 暂停线程 t.suspend(); System.out.println("C="+System.currentTimeMillis() +"\t"+"i="+t.getI()); Thread.sleep(500); System.out.println("C="+System.currentTimeMillis() + "\t"+"i="+t.getI()); } public static class MyThread extends Thread { private long i = 0; public long getI(){ return i; } public void setI(long i){ this.i=i; } @Override public void run() { super.run(); while (true) { i++; } } }
下面来分析一下运行结果:在A段中,先执行的是suspend()暂停线程的方法,所以从结果可以看出,系统的当前时间在变,但是i值确一直是0,说明线程没有在执行,仍是初始化的值,到了B段,执行了resume()恢复线程的方法,从结果也可以看出,当前系统的时间在变,i值也在改变,说面线程已经被恢复并在执行了,到了C段,出现这样的结果和A段原因是一样的。
以上我说了很多小例子,如果亲手敲一遍代码,看一下执行结果,会有更好的理解,毕竟线程执行的结果不是单一的。
时间: 2024-08-27 08:27:12