interrupt()的作用是中断本线程,本线程中断自己是被允许的,其他线程调用本线程的interrupt()方法时,会通过checkAccess()检查权限,可能会抛出SecurityException异常。
interrupt()和isInterrupted()都能够用于检测对象的“中断标记”,区别是interruptrf()除了返回中断标记外,它还会清除中断标记(即将中断标记设为false),而isInterrupted()仅仅返回中断标记。
一、终止处于“阻塞状态”的线程:
通过中断方式终止处于阻塞状态的线程,当线程由于被调用了sleep(),wait(),join()等方法而进入阻塞状态,此时调用线程的interrupt()将线程的中断标记为true。由于处于阻塞状态,中断标记会被清除,同时产生一个InterruptedException异常,将InterruptedException放在适当的位置就能终止线程,形式如下:
- @Override
- public void run()
- {
- try {
- while (true) {
- // 执行任务...
- }
- } catch (InterruptedException ie) {
- // 由于产生InterruptedException异常,退出while(true)循环,线程终止!
- }
- }
说明:在while(true)中不断的执行任务,当线程处于阻塞状态时,调用线程的interrupt()方法会产生InterruptedException中断,中断的捕获在while(true)之外,这样就退出了while(true)循环。
对InterruptException的捕获一定要放在while(true)循环体的外面,这样产生异常时就退出了while(true)循环,否则,InterruptException在while(true)循环体之外,就需要额外的添加退出处理,形式如下:
- @Override
- public void run() {
- while (true) {
- try {
- // 执行任务...
- } catch (InterruptedException ie) {
- // InterruptedException在while(true)循环体内。
- // 当线程产生了InterruptedException异常时,while(true)仍能继续运行!需要手动退出
- break;
- }
- }
- }
上面的InterruptedException异常的捕获是在while(true)中,当产生异常被catch时,仍然在while(true)循环体内,要退出while(true)循环体,需要额外的执行 操作。
二、终止处于运行状态的线程
通过标记方式终止处于运行状态的线程,其中,包括“中断标记”和“额外添加标记”
(1)通过“中断标记”终止线程,形式如下:
- @Override
- public void run() {
- while (!isInterrupted()) {
- // 执行任务...
- }
- }
说明:isInterrupted()是判断线程的中断标记是不是为true,当前线程处于运行状态,并且我们需要终止它时,可以调用线程的interrupt()方法,使用线程的中断标记为true,即isInterrupted()会返回true,此时,就会退出while循环。
interrupt()并不会终止处于“运行状态”的线程,它会将线程的中断标记设为true
(2)通过“额外添加标记”,形式如下:
- rivate 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异常产生时,线程被终止。
- }
- }
三、终止线程的示例
interrupt()常常被用来终止“阻塞状态”线程,参考示例:
- class MyThread extends Thread {
- public MyThread(String name) {
- super(name);
- }
- @Override
- public void run() {
- try {
- int i=0;
- while (!isInterrupted())
- {
- System.out.println("thread is running");
- Thread.sleep(100); // 休眠100ms
- i++;
- System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);
- }
- } catch (InterruptedException e) {
- System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException.");
- }
- }
- }
- public class Hello {
- public static void main(String[] args) {
- try {
- Thread t1 = new MyThread("t1"); // 新建“线程t1”
- System.out.println(t1.getName() +" ("+t1.getState()+") is new.");
- t1.start(); // 启动“线程t1”
- System.out.println(t1.getName() +" ("+t1.getState()+") is started.");
- // 主线程休眠300ms,然后主线程给t1发“中断”指令。
- System.out.println("MainThread sleep");
- Thread.sleep(300);
- System.out.println("Thread interrupt");
- t1.interrupt();
- System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");
- // 主线程休眠300ms,然后查看t1的状态。
- System.out.println("MainThread sleep");
- Thread.sleep(300);
- System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
运行结果:
t1 (NEW) is new.
t1 (RUNNABLE) is started.
MainThread sleep
thread is running
t1 (RUNNABLE) loop 1
thread is running
t1 (RUNNABLE) loop 2
thread is running
t1 (RUNNABLE) loop 3
thread is running
Thread interrupt
t1 (TIMED_WAITING) is interrupted.
MainThread sleep
t1 (RUNNABLE) catch InterruptedException.
t1 (TERMINATED) is interrupted now.
结果说明:
(1)主线程main中会通过new MyThread("t1")创建线程t1,之后通过t1.start()启动线程t1
(2)t1启动之后,会不断的检查他的中断标记,如果中断标记为false,则休眠100ms
(3)t1休眠之后会切换到主线程main,主线程再次运行时,会执行t1.interrupt()中断线程t1。t1收到中断指令之后,会将t1的中断标志设置为false,而且会抛出InterruptedException异常,在t1的run()方法中,是在循环体之外捕获的异常,因此循环被终止。
通过“额外添加标记”的方式终止“运行状态”的线程的示例:
- class MyThread extends Thread {
- private volatile boolean flag= true;
- public void stopTask() {
- flag = false;
- }
- public MyThread(String name) {
- super(name);
- }
- @Override
- public void run() {
- synchronized(this) {
- try {
- int i=0;
- while (flag) {
- Thread.sleep(100); // 休眠100ms
- i++;
- System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);
- }
- } catch (InterruptedException ie) {
- System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException.");
- }
- }
- }
- }
- public class Hello {
- public static void main(String[] args) {
- try {
- MyThread t1 = new MyThread("t1"); // 新建“线程t1”
- System.out.println(t1.getName() +" ("+t1.getState()+") is new.");
- t1.start(); // 启动“线程t1”
- System.out.println(t1.getName() +" ("+t1.getState()+") is started.");
- // 主线程休眠300ms,然后主线程给t1发“中断”指令。
- Thread.sleep(300);
- System.out.println("stopTask");
- t1.stopTask();
- System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");
- // 主线程休眠300ms,然后查看t1的状态。
- Thread.sleep(300);
- System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }