Java多线程系列--“基础篇”09之 interrupt()和线程终止方式(二)
的操作。
2.2 终止处于“运行状态”的线程
通常,我们通过“标记”方式终止处于“运行状态”的线程。其中,包括“中断标记”和“额外添加标记”。
(01) 通过“中断标记”终止线程。
形式如下:
@Override
public void run() {
while (!isInterrupted()) {
// 执行任务...
}
}
说明:isInterrupted()是判断线程的中断标记是不是为true。当线程处于运行状态,并且我们需要终止它时;可以调用线程的interrupt()方法,使用线程的中断标记为true,即isInterrupted()会返回true。此时,就会退出while循环。
注意:interrupt()并不会终止处于“运行状态”的线程!它会将线程的中断标记设为true。
(02) 通过“额外添加标记”。
形式如下:
复制代码
private volatile boolean flag= true;
protected void stopTask() {
flag = false;
}
@Override
public void run() {
while (flag) {
// 执行任务...
}
}
复制代码
说明:线程中有一个flag标记,它的默认值是true;并且我们提供stopTask()来设置flag标记。当我们需要终止该线程时,调用该线程的stopTask()方法就可以让线程退出while循环。
注意:将flag定义为volatile类型,是为了保证flag的可见性。即其它线程通过stopTask()修改了flag之后,本线程能看到修改后的flag的值。
综合线程处于“阻塞状态”和“运行状态”的终止方式,比较通用的终止线程的形式如下:
复制代码
@Override
public void run() {
try {
// 1. isInterrupted()保证,只要中断标记为true就终止线程。
while (!isInterrupted()) {
// 执行任务...
}
} catch (InterruptedException ie) {
// 2. InterruptedException异常保证,当InterruptedException异常产生时,线程被终止。
}
}
复制代码
3. 终止线程的示例
interrupt()常常被用来终止“阻塞状态”线程。参考下面示例:
复制代码
1 // Demo1.java的
源码
2 class MyThread extends Thread {
3
4 public MyThread(String name) {
5 super(name);
6 }
7
8 @Override
9 public void run() {
10 try {
11 int i=0;
12 while (!isInterrupted()) {
13 Thread.sleep(100); // 休眠100ms
14 i++;
15 System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);
16 }
17 } catch (InterruptedException e) {
18 System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException.");
19 }
20 }
21 }
22
23 public class Demo1 {
24
25 public static void main(String[] args) {
26 try {
27 Thread t1 = new MyThread("t1"); // 新建“线程t1”
28 System.out.println(t1.getName() +" ("+t1.getState()+") is new.");
29
30 t1.start(); // 启动“线程t1”
31 System.out.println(t1.getName() +" ("+t1.getState()+") is started.");
32
33 // 主线程休眠300ms,然后主线程给t1发“中断”指令。
34 Thread.sleep(300);
35 t1.interrupt();
36 System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");
37
38 // 主线程休眠300ms,然后查看t1的状态。
39 Thread.sleep(300);
40 System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
41 } catch (InterruptedException e) {
42 e.printStackTrace();
43 }
44 }
45 }
复制代码
运行结果:
复制代码
t1 (NEW) is new.
t1 (RUNNABLE) is started.
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
t1 (TIMED_WAITING) is interrupted.
t1 (RUNNABLE) catch InterruptedException.
t1 (TERMINATED) is interrupted now.
复制代码
结果说明:
(01) 主线程main中通过new MyThread("t1")创建线程t1,之后通过t1.start()启动线程t1。
(02) t1启动之后,会不断的检查它的中断标记,如果中断标记为“false”;则休眠100ms。
(03) t1休眠之后,会切换到主线程main;主线程再次运行时,会执行t1.interrupt()中断线程t1。t1收到中断指令之后,会将t1的中断标记设置“false”,而且会抛出InterruptedException异常。在t1的run()方