java线程正确的终止方式【被interrupt迷惑了这么久】
java线程中关于中断的三个重要方法
interrupt(),isInterrupted()和interrupted()
解释:
interrupt():调用某线程的interrupt()方法会改变当前线程的中断状态,但是不会终止当前线程的运行,那么此线程终止不终止还是取决于线程中的代码。
isInterrupted():该方法用来判断某线程的终端状态,返回true/false
interrupted():该方法用于检测中断并清除中断状态,注意该方法为静态方法,只作用于当前线程
interrupt()方法
注意不要被interrupt方法迷惑,interrupt方法不能终止正常执行的程序,而只是会改变该线程的中断状态而已,就像线程中的一个属性一样(只是比喻而已,其实一点也不一样)。它和Thread.stop方法完全不一样,Thread.stop确实停止了一个正在运行的线程,然而,这种方法是不安全也是不受提倡的。
代码案例:
public class ExamApplicationTests{
static volatile boolean stop;
public static void main(String[] args) {
Thread t=new Thread(new Runnable() {
@Override
public void run() {
while(!stop) {
System.out.println("running...");
long time = System.currentTimeMillis();
while((System.currentTimeMillis()-time < 1000)) {
//延时一秒
}
}
}
});
t.start();
t.interrupt();
System.out.println("中断线程"+t.isInterrupted());
}
}
程序输出:
中断线程true
running...
running...
running...
running...
running...
running...
...
由此可以看出interrupt方法并没有终止线程的执行。
如何终止一个线程
中断线程最好的,最受推荐的方式是,使用共享变量发出信号,告诉线程必须停止正在运行的任务。然而线程必须周期性的核查这一变量,然后有秩序地中止任务。
例:
public class ExamApplicationTests{
static volatile boolean stop;
public static void main(String[] args) throws InterruptedException {
Thread t=new Thread(new Runnable() {
@Override
public void run() {
while(!stop) {
System.out.println("running...");
long time = System.currentTimeMillis();
while((System.currentTimeMillis()-time < 1000)) {
//延时一秒
}
}
System.out.println("线程结束");
}
});
t.start();
Thread.sleep(3000);
stop=true;
}
}
程序输出:
running...
running...
running...
线程结束
interrupt存在的意义是什么?
刚才说过可以用共享变量的方式终止线程,但前提是该线程必须周期性的核查这一变量。那么就要考虑,如果当前线程正在处于阻塞状态怎么办?那么此时执行interrupt方法就变得有意义了,如果线程执行interrupt方法时,该线程处于Thread.sleep(), Thread.join()或 Object.wait()这三种阻塞状态,那么该线程将取消阻塞,并且抛出InterruptedException异常,那么我们就有机会在捕获异常后处理终止任务的逻辑。
例:
public class ExamApplicationTests{
static volatile boolean stop;
public static void main(String[] args) throws InterruptedException {
Thread t=new Thread(new Runnable() {
@Override
public void run() {
//任务逻辑
try {
Thread.sleep(10000);//睡眠10秒,处于阻塞状态
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("任务终止");
return ;
}
//其他任务逻辑...
System.out.println("线程结束");
}
});
t.start();
System.out.println("Thread start");
t.interrupt();
System.out.println("Thread end");
stop=true;
}
}
程序输出:
Thread start
Thread end
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.dzqc.exam.ExamApplicationTests$1.run(ExamApplicationTests.java:12)
at java.lang.Thread.run(Unknown Source)
任务终止
可以通过这种方式提早的结束线程的阻塞状态,从而执行终止逻辑。