您的位置:首页 > 编程语言 > Java开发

任务的取消与关闭(java并发编程实践读书笔记六)

2011-11-17 23:35 239 查看
可取消的任务:外部代码能够在任务自然完成之前,把他更改为完成状态。

取消策略 :一个可取消的任务必须拥有取消策略

策略主要说明

其他代码如何取消该任务。例:在任务中提供public的cancel方法
任务本身在什么时候检查取消的请求是否到达
任务响应取消请求要执行哪些动作

一种取消策略

在任务(线程)中定义一个取消标志 volatile boolean cancelled ,使用volatile域保证其可见性

在任务(线程)中定义一个方法 public void cancel()用来设置变量cancelled的值

在run方法的某个方便取消任务的位置检查该变量 如果变量被其他线程修改 则在方便的时候取消任务

缺点:当检查取消标志之前存在阻塞的方法时,可能永远都不会检查到这个标志,cancel方法也就变得没有意义了

代码:

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

public class PrimeGenerator implements Runnable {
private final List<BigInteger>
primes = new ArrayList<BigInteger>();
private volatile boolean
cancelled = false;
@Override
public void run() {
BigInteger p = BigInteger.ONE;
while(!cancelled){
p=p.nextProbablePrime();
synchronized(this){
primes.add(p);
}
}
}
public void cancel(){
cancelled=true;
}
public synchronized List<BigInteger> get(){
return new ArrayList<BigInteger>(primes);
}
}
这个线程用来产生素数,并不断的放到一个List中,其他线程可以随时从线程中得到已经产生的素数列表,也可以随时调用cancel方法来结束线程。

使用中断来取消任务:

每一个线程都有一个boolean类型的中断状态,在中断的时候为true

Thread还包含了中断状态相关的方法

public
class Thread{

public void interrupt(){...}
public boolean isInterrupted(){...}
public static boolean interrupted(){...}

}

interrupt方法中断目标线程
isInterrupted方法返回目标线程当前的中断状态
静态的interrupted方法清除当前线程的中断状态,并返回它之前的值

1.阻塞的库函数(Thread.sleep,Object.wait等)会监视线程的中断状态,并提前返回。它们对中断的响应为:清除中断状态,抛出InterruptedException

try{
Thread.sleep(3000);
}catch(InterruptedException e){
/*允许线程退出*/
}
2.当线程没有处在阻塞状态时发生中断,会设置线程的中断状态,然后等待被中断的线程内部自己检查是否发生了中断。如果没有检查,也没有触发InterruptedException,中断状态就一直这么保持着。
while(!Thread.currentThread().isInterrupted()){ //检查中断状态
...
}

通过以上两点,我们可以认识到:中断并不会真正的中断一个线程,他仅仅是发出了一个
中断请求,线程收到请求后可以选择处理,也可以选择不处理。系统的有些库函数(阻塞的方法)会关注这个状态,并在接到中断之后抛出异常
注意:中断请求最好不要隐藏。静态的interrupted方法会清除中断状态,因此,如果interrupted方法返回true,可以抛出异常或者是再次调用interrupt方法设置中断状态

中断策略
决定如何应对中断请求:尽可能迅速退出,如果需要的话进行清理,可能的话通知其他的实体本线程退出。

在任务代码中应该小心的保存中断状态,因为线程不是隶属于该任务的,对于线程池来讲,一个线程上可能会运行多个任务,任务中小心的保存中断状态,线程的所有者才能最终有所作用。

对于大多数可阻塞的库函数而言,他们之所以仅仅抛出了InterruptedException,是因为他们知道自己没有权限结束一个本来就不属于他们的线程,所以抛出异常,传给上层代码进一步的决定要采取的策略。在捕获了InterruptedException之后,要恢复中断的状态
Thread.currentThread().interrupt();

响应中断
在调用可中断的阻塞函数时 的策略
1.传递异常,这时你的方法也成为可中断的阻塞方法了
public void sleep(int i) throws InterruptedException{
Thread.sleep(i);
}
2.保存中断状态,上层调用者对其处理
在catch语句中回复中断状态 --Thread.currentThread().interrupt()
3.实现含有阻塞方法的不可取消任务
一般来说,含有阻塞方法的任务均可响应中断,可以通过特殊的处理,使任务在退出前保存中断
定义一个自有的中断状态,当阻塞的方法响应中断抛出异常时,catch中把自有的中断状态设置为ture,然后在finally块中检查这个自有的中断状态,然后设置Thread 的中断状态。这样只有在任务结束退出的时候才设置的Thread的中断。实现了不可取消的任务。

这里可能是最后一篇,我自己买了本书,以后笔记就直接写在书上了,不再整理发布了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: