Java线程之InterruptedException

来源:互联网 发布:java中int的范围 编辑:程序博客网 时间:2024/06/01 20:45

1. InterruptedException异常概述

当一个方法后面声明可能会抛出InterruptedException 异常时,说明该方法是可能会花一点时间,但是可以取消的方法。

 

抛InterruptedException的代表方法有:

1. Java.lang.Object 类的 wait 方法

2. java.lang.Thread 类的 sleep 方法

3. java.lang.Thread 类的 join 方法

 

-- 需要花点时间的方法

执行wait方法的线程,会进入等待区等待被notify/notify All。在等待期间,线程不会活动。

执行sleep方法的线程,会暂停执行参数内所设置的时间。

执行join方法的线程,会等待到指定的线程结束为止。

因此,上面的方法都是需要花点时间的方法。

 

-- 可以取消的方法

因为需要花时间的操作会降低程序的响应性,所以可能会取消/中途放弃执行这个方法。

这里主要是通过interrupt方法来取消。

 

1. sleep方法与interrupt方法

interrupt方法是Thread类的实例方法,在执行的时候并不需要获取Thread实例的锁定,任何线程在任何时刻,都可以通过线程实例来调用其他线程的interrupt方法。

当在sleep中的线程被调用interrupt方法时,就会放弃暂停的状态,并抛出InterruptedException异常,这样一来,线程的控制权就交给了捕捉这个异常的catch块了。

 

2. wait方法和interrupt方法

当线程调用wait方法后,线程在进入等待区时,会把锁定接触。当对wait中的线程调用interrupt方法时,会先重新获取锁定,再抛出InterruptedException异常,获取锁定之前,无法抛出InterruptedException异常。

 

3. join方法和interrupt方法

当线程以join方法等待其他线程结束时,一样可以使用interrupt方法取消。因为join方法不需要获取锁定,故而与sleep一样,会马上跳到catch程序块

 

-- interrupt方法干了什么?

interrupt方法其实只是改变了中断状态而已。

而sleep、wait和join这些方法的内部会不断的检查中断状态的值,从而自己抛出InterruptEdException。

所以,如果在线程进行其他处理时,调用了它的interrupt方法,线程也不会抛出InterruptedException的,只有当线程走到了sleep, wait, join这些方法的时候,才会抛出InterruptedException。若是没有调用sleep, wait, join这些方法,或者没有在线程里自己检查中断状态,自己抛出InterruptedException,那InterruptedException是不会抛出来的。

 

isInterrupted方法,可以用来检查中断状态

Thread.interrupt方法,可以用来检查并清除中断状态,interrupt方法只能中断正在阻塞的线程而不对正在运行中的线程无作用。



2. 如何中断一个线程:

1. 使用共享变量(shared variable)发出信号,告诉线程必须停止正在运行的任务。线程必须周期性的核查这一变量(尤其在冗余操作期间),然后有秩序地中止任务。

package ThreadLocalTest;public class TestCase extends Thread {volatile boolean stop = false;public static void main(String[] args) throws InterruptedException {TestCase thread = new TestCase();System.out.println("Starting thread...");thread.start();Thread.sleep(3000);System.out.println("Asking thread to stop...");thread.stop = true;Thread.sleep(3000);System.out.println("Stopping application...");}public void run() {while (!stop) {System.out.println("Thread is running...");long time = System.currentTimeMillis();while ((System.currentTimeMillis() - time < 1000) && (!stop)) {}}System.out.println("Thread exiting under request...");}}

Starting thread...Thread is running...Thread is running...Thread is running...Thread is running...Asking thread to stop...Thread exiting under request...Stopping application...

2.  对于有可能被阻塞的方法,正确的停止线程方式是设置共享变量,并调用interrupt()(注意变量应该先设置)。如果线程没有被阻塞,这时调用interrupt()将不起作用;否则,线程就将得到异常(该线程必须事先预备好处理此状况),接着逃离阻塞状态。在任何一种情况中,最后线程都将检查共享变量然后再停止。Listing C这个示例描述了该技术。

package ThreadLocalTest;public class ThreadBasic extends Thread {volatile static boolean stop = false;public static void main(String[] args) throws InterruptedException {ThreadBasic thread = new ThreadBasic();System.out.println("Starting thread...");thread.start();Thread.sleep(1000);System.out.println("Asking thread to stop...");stop=true;thread.interrupt();Thread.sleep(3000);System.out.println("Stopping application...");}public void run() {while(!stop){System.out.println("Thread running...");try {Thread.sleep(3000);} catch (InterruptedException e) {System.out.println("Thread interrupted...");}System.out.println("Thread exiting under request...");}}}

Starting thread...Thread running...Asking thread to stop...Thread interrupted...Thread exiting under request...Stopping application...

3.如何处理InterruptedException异常

1. 不捕捉,将它传递给调用者

2. 捕捉后恢复中断状态 

      有时候抛出 InterruptedException 并不合适,例如当由Runnable 定义的任务调用一个可中断的方法时,就是如此。在这种情况下,不能重新抛出InterruptedException,但是您也不想什么都不做。当一个阻塞方法检测到中断并抛出InterruptedException 时,它清除中断状态。如果捕捉到InterruptedException 但是不能重新抛出它,那么应该保留中断发生的证据,以便调用栈中更高层的代码能知道中断,并对中断作出响应。该任务可以通过调用interrupt() 以 “重新中断” 当前线程来完成,如清单 3 所示。至少,每当捕捉到InterruptedException 并且不重新抛出它时,就在返回之前重新中断当前线程。

public class TaskRunner implements Runnable {    private BlockingQueue<Task> queue;    public TaskRunner(BlockingQueue<Task> queue) {         this.queue = queue;     }    public void run() {         try {             while (true) {                 Task task = queue.take(10, TimeUnit.SECONDS);                 task.execute();             }         }         catch (InterruptedException e) {              // Restore the interrupted status             Thread.currentThread().interrupt();         }    }}




中断线程

处理InterruptedException

InterruptedException介绍

0 0