以下demo是错误的终止线程的demo(使用thread.stop()方法实现终止线程):
public class ErrorStopThreadDemo {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程终止结束");
}
});
thread.start();
thread.stop();
}
}
输出结果:
说明:
- 使用thread.stop方法来终止线程就类似于在linux系统中使用 kill -9 pid进行进程的终止,这种终止线程的方式不管线程是否执行完毕就直接终止线程。是不正确的,所以输出的结果中没有输出“线程终止结束”几个字。
线程友好终止的前提条件时线程执行的逻辑要完全执行结束。
以下是正确地终止线程的方法一Demo:
public class CorrectStopThreadDemo1 {
volatile boolean stop = false;
public static void main(String[] args) {
CorrectStopThreadDemo1 demo1 = new CorrectStopThreadDemo1();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while (!demo1.stop){
}
System.out.println("线程结束");
}
});
thread.start();
demo1.stop = true;
}
}
执行结果:
说明:
- 这种中断线程的方法是根据一个标志变量stop变量进行是否终止。
- 因为stop使用了volatile 关键字修饰,所以具有可见性,主线程对它的修改立即被线程thread看见,然后就跳出while循环,执行后面的语句,友好地终止线程。
以下是正确地终止线程的方法2Demo:
首先介绍一下thread.interrupt()方法:
作用:当其它线程调用当前线程的interrupt方法,表示向当前线程打个招呼,告诉它中断线程可以执行了,至于什么时候中断,取决于当前线程自己。
public class CorrectStopThreadDemo2 {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
//实际上是修改中断标志位,与方法1类似,不过这个标志位是在JVM中维护的。
//调用interrupt方法会使isInterrupted返回true。跳出while循环。
while (!Thread.currentThread().isInterrupted()){
}
System.out.println("终止线程");
}
});
thread.start();
//主线程调用thread线程的interrupt方法,告诉thread线程中断线程可以执行了。
thread.interrupt();
}
}
执行结果:
说明:
- interrupt方法再改终止方法中的作用是修改标志位。使得程序跳出循环,正确终止。
线程终止的意义:
- 对正常的任务进行线程终止没有意义。
有意义的终止线程的场景: - while循环:通过一个终止标志位来实现线程的终止。
- 线程要处于阻塞状态下进行终止才有意义。
- Thread.join() Thread.sleep() obj.wait() 这些方法会导致线程阻塞,在一定的业务场景下对其进行正确的终止是有意义的。
以下是对 thread.join,Thread.sleep() obj.wait() 方法进行正确终止的demo:
public class CorrectStopThreadDemo3 {
public static void main(String[] args) {
CorrectStopThreadDemo3 demo3 = new CorrectStopThreadDemo3();
demo3.stopWait();
demo3.stopSleep();
demo3.stopJoin();
}
public void stopSleep(){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
//睡500秒
TimeUnit.SECONDS.sleep(500);
} catch (InterruptedException e) {
//调用该线程的interrupt方式会抛出InterruptedException异常,
//然后被这里捕获到,然后执行余下代码
e.printStackTrace();
}
System.out.println("线程终止");
}
});
thread.start();
//不想线程执行那么久将其终止。
thread.interrupt();
}
public void stopWait(){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
synchronized (this){
try {
//睡500秒
this.wait();
} catch (InterruptedException e) {
//调用该线程的interrupt方式会抛出InterruptedException异常,
//然后被这里捕获到,然后执行余下代码
e.printStackTrace();
}
System.out.println("线程终止");
}
}
});
thread.start();
//不想线程执行那么久将其终止。
thread.interrupt();
}
public void stopJoin(){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.currentThread().join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
thread.interrupt();
}
}
执行结果:
说明:
- 这种方法的终止是通过执行当前线程的interrupt方法抛出了一个InterruptedException异常,然后执行异常代码块,然后执行下面的逻辑代码,正确终止线程。
Thread.interrupted()方法解释:
作用:
对设置中断标志的线程复位默认值,并且返回当前中断状态。
public class InterruptedDemo {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("没有执行interrupt方法的中断标志值="+Thread.currentThread().isInterrupted());
Thread.interrupted();
System.out.println("没有执行interrupt方法然后复位后的中断标志值="+Thread.currentThread().isInterrupted());
while (!Thread.currentThread().isInterrupted()){
}
System.out.println("执行了interrupt方法的中断标志值="+Thread.currentThread().isInterrupted());
Thread.interrupted();
System.out.println("执行了interrupt方法后复位后的中断标志值="+Thread.currentThread().isInterrupted());
}
});
thread.start();
//这里睡眠1s是为了把线程的while循环之前的代码执行完。
TimeUnit.SECONDS.sleep(1);
thread.interrupt();
}
}
执行结果:
说明:
- 没有执行interrupt方法时,中断标志默认false,所以第一个输出为false。
- 没有执行interrupt方法却使用了interrupted方法复位,中断标志恢复默认false,所以第二个输出为false。
- 执行了interrupt方法却没有使用interrupted复位时,中断标志被设置为true。所以第三个输出true。
- 执行了interrupt方法后使用interrupted复位时,中断标志被复位为false,所以第四个输出false。