Java线程之InterruptedException

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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值