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

java中线程的取消

时间:2016-05-12 21:22:23      阅读:183      评论:0      收藏:0      [点我收藏+]

标签:

Java中没有一种安全的抢占式方法来停止线程,只有一种协作式的机制。

大致分为两种协作式机制:1.设置某个”已请求取消“的标志,线程任务定期查看该标志。如果取消标志设置为true,则结束任务

        2.调用线程的interrupt()能中断目标线程,通过Thread.currentThread().isInterrupted()方法来查询,也可以通过大多数可阻塞的库函数(如Thread.sleep和Object.wait)来抛出InterruptedException异常,在异常中退出线程。  

第一种中断方式的实现代码:

public class PrimeGenerator implements Runnable{

private final List<BigInteger> primes=new ArrayList<BigInteger>();

private  volatile boolean cancelled;   //需要将cancelled设置为volatile变量,确保当一个线程修改后,对其他线程是可见的


@Override
public void run() {
// TODO Auto-generated method stub
BigInteger p=BigInteger.ONE;
while(!cancelled){
p=p.nextProbablePrime();
synchronized(this){
primes.add(p);
}
}
}

public void cancel(){
cancelled=true;
}

}

这种中断方式在任务调度一个阻塞方法时,例如BlockingQueue.put方法时,会使线程一直阻塞,任务可能永远不会检查取消标志,因此会出现取消失败的情况


第二种中断方式的实现代码:

public class PrimeProducer implements Runnable{


private final BlockingQueue<BigInteger> queue;

PrimeProducer(BlockingQueue<BigInteger> queue){
this.queue=queue;
}
public void run() {
// TODO Auto-generated method stub
try {
BigInteger p = BigInteger.ONE;
while (!Thread.currentThread().isInterrupted()) {
queue.put(p = p.nextProbablePrime());
// Thread.currentThread().sleep(10);
System.out.println(queue.size());
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("中断了,请处理中断");
}
}
public static void main(String[] args){
BlockingQueue<BigInteger> queue=new ArrayBlockingQueue<BigInteger>(999999);
Thread th1=new Thread(new PrimeProducer(queue));
th1.start();
               try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
                th1.interrupt();
}
}

这种方式使用中断机制才中断,上面代码中有两个位置可以检验出中断:Thread.currentThread().isInterrupted()方法和阻塞方法put的调用。

注意第二种机制的run方法还能写成下面模式,将中断异常处理放在while循环体内,但是必须要在异常处理catch语句块加上Thread.currentThread().interrupt()这句来重置中断状态,否则有可能无法终止任务。这是由于阻塞库方法在检查到线程中断时抛出InterruptException异常前,会清除中断状态。使得while在判断Thread.currentThread().isInterrupted() 时会返回false,则线程不会退出,因此需要在异常处理块重置中断。

public void run() {
// TODO Auto-generated method stub
BigInteger p=BigInteger.ONE;
while(!Thread.currentThread().isInterrupted()){
try {
queue.put(p=p.nextProbablePrime());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("中断了,请处理中断");
Thread.currentThread().interrupt(); ///捕获InterruptedException后恢复中断状态
}
//Thread.currentThread().sleep(10);
System.out.println(queue.size());
  }
}


参考资料

《Java Concurrency in Practice》Brian Goetz等著

java中线程的取消

标签:

原文地址:http://blog.csdn.net/a1548178885/article/details/51352987

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