如何终止java线程

来源:互联网 发布:09和冷冷的故事 知乎 编辑:程序博客网 时间:2024/05/18 19:37

线程停止有3种方式:

(1) 使用退出标识,让线程正常退出,就是加个判断,满足某个判断时,退出程序。

(2) 使用stop方法,已废弃。

(3) 使用interrupt方法中断线程。

1. 使用interrupt方法能让线程正常中断吗?

使用interrupt方法来中断线程,并不能马上就让线程中断,

使用interrupt方法只是在当前线程中打了一个停止的标记,并不是真正的停止线程。

eg:

package com.lanhuigu.JavaBase.thread.stopthread;public class InterruptMethod extends Thread{@Overridepublic void run() {// TODO Auto-generated method stub// 循环50万次for (int i = 0; i < 500000; i++) {System.out.println("i = " + (i+1));}}public static void main(String[] args) {try {InterruptMethod thread = new InterruptMethod();thread.start();// 启动InterruptMethod线程Thread.sleep(2000);// main线程休眠2秒thread.interrupt();// 调用interrupt中断线程} catch (InterruptedException ex) {// TODO: handle exceptionex.printStackTrace();}}}
控制台打印结果:

我们可以把控制台结果拷贝到文本编辑器,确认是否打印50万条日志:

我们从打印结果可以看到确实输出了50万条日志,说明interrupt并没有让线程中断,

因为当InterruptMethod线程启动后,过两秒钟的时间就调用interrupt中断线程,

如果中断了,不能输出50万条日志,2秒的时间做不到。


注意: 如果你的控制台没有打印50万条日志,需要设置一下eclipse控制台输出行数限制。


2. 要想知道线程是否停止,首先需要知道如何判断一个线程是否处于停止状态

在Thread类中,提供了两个方法判断线程是否停止:

(1) interrupted():判断当前线程是否已经中断,同时执行结束时清除线程状态并将线程状态标识为默认状态false。

public static boolean interrupted()


(2) isInterrupted():判断线程是否已经中断,不清除线程的中断状态标识状态。

public boolean isInterrupted()

关于interrupted()示例,测试当前线程是否中断:

package com.lanhuigu.JavaBase.thread.stopthread;public class InterruptMethod extends Thread{@Overridepublic void run() {// TODO Auto-generated method stub// 循环50万次for (int i = 0; i < 500000; i++) {System.out.println("i = " + (i+1));}}public static void main(String[] args) {try {InterruptMethod thread = new InterruptMethod();thread.start();// 启动InterruptMethod线程Thread.sleep(2000);// main线程休眠2秒thread.interrupt();// 调用interrupt中断线程System.out.println("是否停止1:" + thread.interrupted());// 判断是否已经中断System.out.println("是否停止2:" + thread.interrupted());// 判断是否已经中断} catch (InterruptedException ex) {// TODO: handle exceptionex.printStackTrace();}}}
拷贝控制台运行结果到文本编辑器,搜索"是否停止",分别找到两个打印结果:

是否停止1:false

是否停止2:false

判断结果均为false,说明当前线程"main"从未中断过。

根据实验验证interrupted()清空线程状态:

package com.lanhuigu.JavaBase.thread.stopthread;public class Test {public static void main(String[] args) {Thread.currentThread().interrupt();System.out.println("是否停止1:" + Thread.interrupted());System.out.println("是否停止2:" + Thread.interrupted());System.out.println("线程执行结束!");}}
运行结果:

是否停止1:true
是否停止2:false
线程执行结束!

第一次检测的时候,拿到线程中断,所以为true,但是第二次为false,

因为第一次的时候线程状态true被清除,恢复为默认false。


关于isInterrupted()示例,测试线程是否中断:

package com.lanhuigu.JavaBase.thread.stopthread;public class IsInterruptMethod extends Thread{@Overridepublic void run() {// TODO Auto-generated method stubfor (int i = 0; i < 500000; i++) {System.out.println("i = " + (i+1));}}public static void main(String[] args) {try {IsInterruptMethod thread = new IsInterruptMethod();thread.start();Thread.sleep(1000);thread.interrupt();System.out.println("是否停止1:" + thread.isInterrupted());System.out.println("是否停止2:" + thread.isInterrupted());} catch (InterruptedException ex) {// TODO: handle exceptionex.printStackTrace();}}}
运行结果拷贝到文本编辑器,搜索"是否停止",找到运行结果:

是否停止1:true

是否停止2:true

根据打印的结果,isInterrupted()方法并没有清除线程状态标识,所以打印了两个true。


3. 停止线程的方法

停止方法:

(1) 异常法: 判断线程中断状态为true时,抛线程中断异常

(2) 在休眠中停止: 让线程处于休眠状态,再调用interrupt(),线程抛异常中断。

(3) 暴力停止: 调用stop方法,该方法已废弃。

(4) 使用return停止: 方法中的代码遇到return时,该方法运行结束,利用这种手段,

     也能达到线程停止的效果。

******异常法: 判断线程中断状态为true时,抛线程中断异常

eg1:

package com.lanhuigu.JavaBase.thread.stopthread;public class ExceptionMethod extends Thread{@Overridepublic void run() {// TODO Auto-generated method stubfor (int i = 0; i < 500000; i++) {if (this.interrupted()) {// 判断线程是否中断System.out.println("线程已经停止,退出代码执行");break;}System.out.println("i = " + (i+1));}}public static void main(String[] args) {try {ExceptionMethod exceptionMethod = new ExceptionMethod();exceptionMethod.start();Thread.sleep(3000);exceptionMethod.interrupt();} catch (InterruptedException ex) {// TODO: handle exceptionex.printStackTrace();}}}
运行结果:

从运行结果可以看出,线程启动后执行3秒钟的时间,调用interrupt方法,中断了线程,

run方法中拿到线程中断状态,通过break语法中断循环,达到预期效果。

但是这么做存在一个问题,如果for循环下表存在代码,break语句只是跳出for循环,

还会执行run方法中for循环后的代码知道run方法运行结束!

eg2:

package com.lanhuigu.JavaBase.thread.stopthread;public class ExceptionMethod extends Thread{@Overridepublic void run() {// TODO Auto-generated method stubfor (int i = 0; i < 500000; i++) {if (this.interrupted()) {// 判断线程是否中断System.out.println("线程已经停止,退出代码执行");break;}System.out.println("i = " + (i+1));}System.out.println("跳出for循环,执行for循环后的代码");}public static void main(String[] args) {try {ExceptionMethod exceptionMethod = new ExceptionMethod();exceptionMethod.start();Thread.sleep(3000);exceptionMethod.interrupt();} catch (InterruptedException ex) {// TODO: handle exceptionex.printStackTrace();}}}
运行结果:

控制台多输出了: 跳出for循环,执行for循环后的代码

通过break还是有遗留问题,需要通过抛异常方式处理。

eg3:

package com.lanhuigu.JavaBase.thread.stopthread;public class ExceptionMethod extends Thread{@Overridepublic void run() {// TODO Auto-generated method stubtry {for (int i = 0; i < 500000; i++) {if (this.interrupted()) {// 判断线程是否中断System.out.println("线程已经停止,退出代码执行");throw new InterruptedException();}System.out.println("i = " + (i+1));}System.out.println("跳出for循环,执行for循环后的代码");} catch (Exception e) {// TODO: handle exception}}public static void main(String[] args) {try {ExceptionMethod exceptionMethod = new ExceptionMethod();exceptionMethod.start();Thread.sleep(3000);exceptionMethod.interrupt();} catch (InterruptedException ex) {// TODO: handle exceptionex.printStackTrace();}}}
通过: throw new InterruptedException()方式解决线程停止时,执行就停止。

控制台运行结果:


根据运行结果,跑出异常后,for后面的代码没有执行,

说明,当线程停止时,执行即结束,这就是异常法线程停止。

******在休眠中停止: 让线程处于休眠状态,再调用interrupt(),线程抛异常中断。

eg:

package com.lanhuigu.JavaBase.thread.stopthread;/** * 在sleep状态下停止某个线程,会进入catch语句,同时清除线程停止状态值变为false. */public class SleepInterruptThread extends Thread{@Overridepublic void run() {// TODO Auto-generated method stubtry {System.out.println("begin time = " + System.currentTimeMillis());Thread.sleep(500000);// 长时间休眠,测试休眠中调用interrupt方法System.out.println("end time = " + System.currentTimeMillis());} catch (InterruptedException ex) {// TODO: handle exceptionSystem.out.println("catch......");ex.printStackTrace();}}public static void main(String[] args) {try {SleepInterruptThread sleepInterruptThread = new SleepInterruptThread();sleepInterruptThread.start();Thread.sleep(2000);sleepInterruptThread.interrupt();} catch (InterruptedException ex) {// TODO: handle exceptionex.printStackTrace();}}}
运行结果:


******暴力停止: 调用stop方法

eg:

package com.lanhuigu.JavaBase.thread.stopthread;/** * stop方法已经被废弃,同时使用stop方法强制停止线程, * 会导致某些收尾程序未完成,对象"解锁",导致数据不同步, * 出现数据不一致问题。 */public class StopThread extends Thread{private int count = 1;@Overridepublic void run() {// TODO Auto-generated method stubtry {while (true) {count++;System.out.println("count = " + count);Thread.sleep(2000);}} catch (InterruptedException ex) {// TODO: handle exceptionex.printStackTrace();}}public static void main(String[] args) {try {StopThread stopThread = new StopThread();stopThread.start();Thread.sleep(8000);stopThread.stop();} catch (InterruptedException ex) {// TODO: handle exceptionex.printStackTrace();}}}

******使用return停止: 方法中的代码遇到return时,该方法运行结束,利用这种手段,

      也能达到线程停止的效果。

eg:

package com.lanhuigu.JavaBase.thread.stopthread;public class ReturnInterruptThread extends Thread{@Overridepublic void run() {// TODO Auto-generated method stubfor (int i = 0; i < 500000; i++) {if (this.interrupted()) {System.out.println("通过return,实现线程停止效果!");return;}System.out.println(" i = " + (i+1));}}public static void main(String[] args) {try {ReturnInterruptThread returnThread = new ReturnInterruptThread();returnThread.start();Thread.sleep(2000);returnThread.interrupt();} catch (InterruptedException ex) {// TODO: handle exceptionex.printStackTrace();}}}
控制台运行结果:


通过return方式停止程序会导致代码中存在多个return,使得代码不纯净,不整洁,

可读性降低,一般采用异常法停止线程,干净利索。

原创粉丝点击