1、正常运行结束
所谓正常运行结束,我的理解就是程序正常运行结束,线程自动结束。
2. 使用退出标志退出线程
一般run()方法执行完,线程就会正常结束,然而腻,常常有些线程是伺服线程。他们需要长时间的运行,只有在外部某些条件满足的情况下,才能关闭这些线程。使用一个变量来控制循环,例如:最直接的方法就是设一个boolean类型的标志,并通过设置这个标志位true或false来控制while循环是否退出,下面放代码:
private class ThreadE extends Thread {
private volatile boolean isRunning = true;
public void setRunning(boolean isRunning) {
this.isRunning = isRunning;
}
@Override
public void run() {
super.run();
int i=0;
while(isRunning) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
i ++;
Log.i(TAG, "ThreadE==>i="+i);
}
}
}
private void testThread() {
ThreadE threadE = new ThreadE();
threadE.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//加入变量可以正常停止线程
threadE.setRunning(false);
}
这里定义了一个是否正在运行的标志isRunning,当isRunning为true时(默认为true),线程正在运行,当isRunning为false时,while循环退出。在定义isRunning时使用了一个Java关键字volatile,这个关键字的目的是使isRunning同步,也就是说在同一时刻只能由一个线程来修改isRunning的值。
输出结果:
ThreadE==>i=1
ThreadE==>i=2
ThreadE==>i=3
ThreadE==>i=4
ThreadE==>i=5
ThreadE==>i=6
ThreadE==>i=7
ThreadE==>i=8
ThreadE==>i=9
ThreadE==>i=10
ThreadE==>thread run end
可见线程正常退出了。
3.Interrupt方法结束线程
(3.1)首先看一个调用intterrupt方法中断不了的例子:
private class ThreadF extends Thread {
@Override
public void run() {
super.run();
int i=0;
while(!isInterrupted()) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
//此处捕捉异常之后,不做任何操作
}
i ++;
Log.i(TAG, "ThreadF==>i="+i+", isInterrupted="+isInterrupted());
}
Log.d(TAG, "ThreadF==>thread end...isInterrupted="+isInterrupted());
}
}
private void testThread05() {
ThreadF threadF = new ThreadF();
threadF.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadF.interrupt();
//或者调用stop中断异常
/**try {
//调用stop会抛出异常Caused by: java.lang.UnsupportedOperationException,
//加上try...catch即可
threadD.stop();
} catch (Exception e) {
e.printStackTrace();
}**/
}
输出如下:
ThreadF==>i=1, isInterrupted=false
ThreadF==>i=2, isInterrupted=false
ThreadF==>i=3, isInterrupted=false
ThreadF==>i=4, isInterrupted=false
ThreadF==>i=5, isInterrupted=false
ThreadF==>i=6, isInterrupted=false
ThreadF==>i=7, isInterrupted=false
ThreadF==>i=8, isInterrupted=false
ThreadF==>i=9, isInterrupted=false
......
ThreadF==>i=200, isInterrupted=false
ThreadF==>i=201, isInterrupted=false
......
此时调用interrrupt或stop方法无法结束线程,
看下面两种方法的解决方案:
(3.2)方法一:
线程处于阻塞状态:如使用了sleep,同步锁的wait(),socket中的receiver(),accept()等方法时,会使线程处于阻塞状态。当调用线程interrupt()方法时,会抛出InterruptException异常。阻塞中的那个方法抛出这个异常,通过代码可以捕获该异常,然后跳出循环状态,从而让我们有机会结束这个线程的执行。通常有些小伙伴认为只要调用interrupt方法,线程就会结束,实际上是不正确的,一定要先捕获InterruptException异常之后通过break来跳出循环,才能正常结束run()方法。
private class ThreadF extends Thread {
@Override
public void run() {
super.run();
int i=0;
while(!isInterrupted()) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
//当线程调用interrupt中断线程时,此处捕捉到异常,并通过break跳出循环也可以结束线程
Log.i(TAG, "catch execption...break while loop...");
break;
}
i ++;
Log.i(TAG, "ThreadF==>i="+i+", isInterrupted="+isInterrupted());
}
Log.d(TAG, "ThreadF==>thread end...isInterrupted="+isInterrupted());
}
}
private void testThread05() {
ThreadF threadF = new ThreadF();
threadF.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//调用interrupt中断线程
threadF.interrupt();
}
输出结果:
ThreadF==>i=1, isInterrupted=false
ThreadF==>i=2, isInterrupted=false
ThreadF==>i=3, isInterrupted=false
ThreadF==>i=4, isInterrupted=false
ThreadF==>i=5, isInterrupted=false
ThreadF==>i=6, isInterrupted=false
ThreadF==>i=7, isInterrupted=false
ThreadF==>i=8, isInterrupted=false
ThreadF==>i=9, isInterrupted=false
catch execption...break while loop...
ThreadF==>thread end...isInterrupted=false //可见跳出循环之后,isInterrupted依然为false
线程结束。
(3.3)方法二:
和方式一很相似,也是通过捕捉InterruptedException异常来结束线程,只不过在捕获异常之后,再次调用interrupt()方法来结束的,对方式一代码更改如下:
private class ThreadF extends Thread {
@Override
public void run() {
super.run();
int i=0;
while(!isInterrupted()) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
//当主动调用interrupt时,就能捕捉中断异常,再次调用interrupt即可中断
interrupt();
Log.i(TAG, "catch exception...isInterrupted="+isInterrupted());
}
i ++;
Log.i(TAG, "ThreadF==>i="+i+", isInterrupted="+isInterrupted());
}
Log.d(TAG, "ThreadF==>thread end...isInterrupted="+isInterrupted());
}
}
private void testThread05() {
ThreadF threadF = new ThreadF();
threadF.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadF.interrupt();
}
输出结果:
ThreadF==>i=1, isInterrupted=false
ThreadF==>i=2, isInterrupted=false
ThreadF==>i=3, isInterrupted=false
ThreadF==>i=4, isInterrupted=false
ThreadF==>i=5, isInterrupted=false
ThreadF==>i=6, isInterrupted=false
ThreadF==>i=7, isInterrupted=false
ThreadF==>i=8, isInterrupted=false
ThreadF==>i=9, isInterrupted=false
catch execption...break while loop...
ThreadF==>i=10, isInterrupted=true
ThreadF==>thread end...isInterrupted=true//再次调用interrupt()方法之后,isInterrupted为true了
4.stop()方法终止线程(不安全)
这个各位小伙伴应该在学习中都有用过吧,我们可以直接使用thread.stop()来强行终止线程,但是stop()方法是很危险的,就想突然关闭电源一样。这样子可能机会产生不可预料的结果,不安全主要是:
thread.stop()调用之后,创建子线程的线程就会抛出ThreadDeatherror的错误,并且会释放子线程所持有的所有锁。一般任何进行加锁的代码块,都是为了保护数据的一致性,如果在调用thread.stop()后导致了该线程所持有的所有的锁突然释放,那么被保护的数据就可能呈现不一致性,其他线程在使用这些被破坏的数据时,有可能导致一些很奇怪的应用程序错误。因此,并不推荐使用stop()方法来终止线程。
————————————————
参考:
https://blog.csdn.net/weixin_44118963/article/details/119721513
https://segmentfault.com/a/1190000039696074?sort=newest
网友评论