码迷,mamicode.com
首页 > 编程语言 > 详细

第七章:取消与关闭——Java并发编程实战

时间:2016-11-06 02:00:31      阅读:152      评论:0      收藏:0      [点我收藏+]

标签:决定   tput   super   处理   throws   socket   通过   提前   pre   

Java没有提供任何机制来安全地终止线程(虽然Thread.stop和suspend方法提供了这样的机制,但由于存在缺陷,因此应该避免使用

中断:一种协作机制,能够使一个线程终止另一个线程的当前工作

立即停止会使共享的数据结构处于不一致的状态,需要停止时,发出中断请求,被要求中断的线程处理完他当前的任务后会自己判断是否停下来

 

一、任务取消

若外部代码能在某个操作正常完成之前将其置入“完成”状态,则还操作是可取消的。(用户请求取消、有时间限制的操作<并发查找结果,一个线程找到后可取消其他线程>、应用程序事件、错误、关闭)

取消策略:详细地定义取消操作的“How”、“When”以及“What”,即其他代码如何(How)请求取消该任务,任务在何时(When)检查是否已经请求了取消,以及在响应取消请求时应该执行哪些(What)操作

举例:设置volatile变量为取消标志,每次执行前检查

 1 private volatile boolean canceled;
 2     
 3     @Override
 4     public void run() {
 5         BigInteger p = BigInteger.ONE;
 6         while (!canceled){
 7             p = p.nextProbablePrime();
 8             synchronized (this) { //同步添加素数
 9                 primes.add(p);
10             }
11         }
12     }

注意:这是一个有问题的取消方式,若线程阻塞在add操作后,那么即使设置了取消状态,它也不会运行到检验阻塞状态的代码,因此会永远阻塞

1、中断

  线程可以通过这种机制来通知另一个线程,告诉它在合适的或者可能的情况下停止当前工作,并转而执行其他的工作。(在取消之外的其他操作使用中断都是不合适的)

  调用interrupt并不意味者立即停止目标线程正在进行的工作,而只是传递了请求中断的消息。会在下一个取消点中断自己,如wait, sleep,join等

1 public class Thread {
2      public void interrupt() { ... }//中断目标线程,恢复中断状态
3      public boolean isInterrupted() { ... }//返回目标线程的中断状态
4      public static boolean interrupted() { ... }//清除当前线程的中断状态,并返回它之前的值(用于已经设置了中断状态,但还尚未相应中断)
5      ...
6  }

阻塞库方法,例如Thread.sleep和Object.wait等,都会检查线程何时中断,并且在发现时提前返回。它们在响应中断时执行的操作包括 : 清除中断状态,抛出InterruptedException,表示阻塞操作由于中断而提前结束

 

  • 显示的检测中断!Thread.currentThread().isInterrupted()后推出
  • 阻塞方法中抓到InterruptedException后退出

2、中断策略——规定线程如何解释某个中断请求——当发现中断请求时,应该做哪些工作

  由于每个线程拥有各自的中断策略,因此除非你知道中断对该线程的含义,否则就不应该中断这个线程。

3、响应中断

  • 传递异常(throws InterruptedException)

  • 恢复中断状态,从而事调用栈的上层代码能够对其进行处理。(Thread.currentThread().interrupt();)

4、通过Future实现取消

  boolean cancel(boolean mayInterruptIfRunning);

  • 如果任务已完成、或已取消,或者由于某些其他原因而无法取消,则此尝试将失败,返回false
  • 调用cancel时,如果调用成功,而此任务尚未启动,则此任务将永不运行
  • 如果任务已经执行,mayInterruptIfRunning参数决定了是否向执行任务的线程发出interrupt操作

5、处理不可中断的阻塞——对于某些阻塞操作,只是设置了中断状态

  • Java.io包中的同步Socket I/O。虽然InputStream和OutputStream中的read和write等方法都不会响应中断,但通过关闭底层的套接字,可以使得由于执行read或write等方法而被阻塞的线程抛出一个SocketException。
  • Java.io包中的同步I/O。当中断一个正在InterruptibleChannel上等待的线程时,将抛出ClosedByInterruptedException)并关闭链路(这还会使得其他在这条链路上阻塞的线程同样抛出ClosedByInterruptException)。当关闭一个InterruptibleChannel时,将导致所有在链路操作上阻塞的线程抛出AsynchronousCloseException。大多数标准的Channel都实现了InterruptibleChannel。
  • Selector的异步I/O。如果一个线程在调用Selector.select方法(在java.nio.channels中)时阻塞了,那么调用close或wakeup方法会使线程抛出ClosedSelectorException并提前返回。
  • 获取某个锁。如果一个线程由于等待某个内置锁而被阻塞,那么将无法响应中断,因为线程认为它肯定获得锁,所以将不会理会中断请求。但是,在Lock类中提供了lockInterruptibly方法,该方法允许在等待一个锁的同时仍能响应中断。
 1 //改写interrupt方法发出中断请求   
 2  @Override
 3     public void interrupt() {
 4         try {
 5             socket.close(); //中断前关闭socket
 6         } catch (IOException e) {
 7             
 8         } finally{
 9             super.interrupt();
10         }
11     }

6、采用newTaskFor来封装非标准的取消

第七章:取消与关闭——Java并发编程实战

标签:决定   tput   super   处理   throws   socket   通过   提前   pre   

原文地址:http://www.cnblogs.com/HectorHou/p/6034274.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!