JAVA八线程之中断机制(怎么样处理搁浅?)

一,介绍

那篇小说首要记录使用 interrupt()
方法中断线程,以及怎么样对InterruptedException举行拍卖。感觉对InterruptedException分外举办拍卖是一件谨慎且有技术的活计。

出于采取stop()方法结束线程分外的强力,人家线程运行的美艳的,突然就把人家杀死了,线程占用的锁被挟持释放,极易造成数据的不同性。可参考那篇作品对stop()方法的介绍。

故而,提议了一种温柔的法门:请求别的多少个线程不要再实施了,那便是暂停情势。

 

二,中断及如何响应中断?

什么样优雅地响应中断真的是太高深了,看到那篇小说:Java 理论与实施: 处理
InterruptedException
就吓了一跳。上边只是记录一些最简便易行的自己对响应中断的了然。

如若某些线程要不停地拍卖某件事情(比如 i
平素自增),不过还有个须要:在拍卖工作前,先要检查下这些线程是还是不是被中止,假若已经被搁浅,处理就相应结束。

上面是有个别例子,这么些事例摘自书本:

 1 public class Run {
 2 
 3     public static void main(String[] args) {
 4         try {
 5             MyThread thread = new MyThread();
 6             thread.start();
 7             Thread.sleep(20);//modify 2000 to 20
 8             thread.interrupt();//请求中断MyThread线程
 9         } catch (InterruptedException e) {
10             System.out.println("main catch");
11             e.printStackTrace();
12         }
13         System.out.println("end!");
14     }
15 }

main线程睡眠20ms后,执行第玖行中断MyThread线程。

 

 1 public class MyThread extends Thread {
 2     @Override
 3     public void run() {
 4         super.run();
 5         for (int i = 0; i < 500000; i++) {
 6             if (this.interrupted()) {
 7                 System.out.println("should be stopped and exit");
 8                 break;
 9             }
10             System.out.println("i=" + (i + 1));
11         }
12         System.out.println("this line is also executed. thread does not stopped");//尽管线程被中断,但并没有结束运行。这行代码还是会被执行
13     }
14 }

当MyThread获得CPU执行时,第伍行的 if
测试中,检查和测试到中断标识被设置。即MyThread线程检查和测试到了main线程想要中断它的
请求。

多数景况下,MyThread检查和测试到了中断请求,对该中断的响应是:退出执行(可能说是结束执行)。

可是,上边第⑤至8行for循环,是推行break语句跳出for循环。不过,线程并从未甘休,它只是跳出了for循环而已,它还会继续执行第22行的代码….

之所以,大家的题材是,当接受了中断请求后,怎样收场该线程呢?

一种有效的法子是行使 return 语句 而不是 break语句。。。。。哈哈。。。

自然,一种更优雅的艺术则是:抛出InterruptedException非凡。

看上边MyThread类的代码:

 1 public class MyThread extends Thread {
 2     @Override
 3     public void run() {
 4         super.run();
 5         try{
 6             for (int i = 0; i < 500000; i++) {
 7                 if (this.interrupted()) {
 8                     System.out.println("should be stopped and exit");
 9                     throw new InterruptedException();
10                 }
11                 System.out.println("i=" + (i + 1));
12             }
13             System.out.println("this line cannot be executed. cause thread throws exception");//这行语句不会被执行!!!
14         }catch(InterruptedException e){
15             System.out.println("catch interrupted exception");
16             e.printStackTrace();
17         }
18     }
19 }

当MyThread线程检查和测试到中断标识为true后,在第八行抛出InterruptedException格外。那样,该线程就不可能再实施其余的健康语句了(如,第三3行语句不会实行)。此地申明:interrupt()方法有多个功效,三个是将线程的间歇状态置位(中断状态由false变成true);另1个则是:让被暂停的线程抛出InterruptedException至极。

那是很要紧的。那样,对于那个打断方法(比如 wait() 和
sleep())而言,当另三个线程调用interrupt()中断该线程时,该线程会从阻塞状态退出并且抛出暂停格外。那样,大家就足以捕捉到中断很是,并依据实况对该线程从绿灯方法中12分退出而开始展览部分拍卖。

譬如:线程A拿到了锁进入了伙同代码块中,但由于条件不足调用 wait()
方法阻塞了。那么些时候,线程B执行
threadA.interrupt()请求中断线程A,此时线程A就会抛出InterruptedException,大家就可以在catch中捕获到这几个丰盛并开展对应处理(比如进一步往上抛出)

 

据此,上面正是三个行使抛出分外的措施来终止线程的演示。即便该示例的实用性十分小。原因在
IBM的那篇博文中:大家 生吞了暂停。

在第③4行,我们一向catch了要命,然后打印输出了一下罢了,调用栈中的更高层的代码是无能为力赢得有关该特别的新闻的。

第叁6行的e.printStackTrace()功效就也就是

“(仅仅记录 InterruptedException 也不是明智的做法,因为等到人来读取日志的时候,再来对它作出处理就为时已晚了。)”---摘自参考博文

 

上边大家是在run()方法中抛出12分,符合那里描述的:

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

 

因为,run方法是落实的Runnable接口中的方法。不可能像上边那样定义,也即上面所说的:“无法重复抛出InterruptedException”。

        @Override
        public void run() throws InterruptedException{//这是错误的
          //do something...

 

就此,多少个更好的缓解方案是:调用 interrupt() 以 “重新中断”
当前线程。创新MyThread类中catch非凡的点子,如下:

 1 public class MyThread extends Thread {
 2     @Override
 3     public void run() {
 4         super.run();
 5         try{
 6             for (int i = 0; i < 500000; i++) {
 7                 if (this.interrupted()) {
 8                     System.out.println("should be stopped and exit");
 9                     throw new InterruptedException();
10                 }
11                 System.out.println("i=" + (i + 1));
12             }
13             System.out.println("this line cannot be executed. cause thread throws exception");
14         }catch(InterruptedException e){
15             /**这样处理不好
16              * System.out.println("catch interrupted exception");
17              * e.printStackTrace();
18              */
19              Thread.currentThread().interrupt();//这样处理比较好
20         }
21     }
22 }

如此,就由 生吞分外 变成了 将 相当事件 进一步扩散了。

 

参报考博士学士文:Java 理论与实施: 处理
InterruptedException

相关文章