java线程中断方式
来源:互联网 发布:tsp 遗传算法 java 编辑:程序博客网 时间:2024/04/30 12:25
Java中没有一种安全的抢占式方法来停止线程,只有一种协作式的机制。
大致分为两种协作式机制:1.设置某个”已请求取消“的标志,线程任务定期查看该标志。如果取消标志设置为true,则结束任务
2.调用线程的interrupt()能中断目标线程,通过Thread.currentThread().isInterrupted()方法来查询,也可以通过大多数可阻塞的库函数(如Thread.sleep和Object.wait)来抛出InterruptedException异常,在异常中退出线程。
第一种中断方式的实现代码:
public class PrimeGenerator implements Runnable { private final List primes = new ArrayList(); 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 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()); } } 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线程中断方式
- Java线程:线程中断
- Future方式中断线程实现
- Java线程中断机制-如何中断线程
- 中断JAVA线程
- 中断JAVA线程
- 中断Java线程
- 中断JAVA线程
- 正确中断java线程
- 中断JAVA线程
- Java 可中断线程
- 中断Java线程
- Java 线程中断
- java线程中断
- Java线程中断
- 如何中断JAVA线程
- JAVA线程中断
- Java线程中断
- php匿名函数与闭包的简单使用
- 三十分钟掌握STL
- OpenCV3.1开发系列-OpenCV2.4.13更新介绍
- ORMlite多表关联查询实现
- Python中获取某个用户对某个文件或目录的访问权限
- java线程中断方式
- hdu 5578 Friendship of Frog 2015ACM/ICPC亚洲区上海站-重现赛
- 深入理解Java:注解(Annotation)基本概念
- thinkphp控制器变量在模板中显示
- NoSQL之Morphia操作MongoDB
- 指针数组和数组指针
- 把玩之python爬虫urllib2高级篇
- 【Android】31、常见控件的使用方法——ProgressBar
- 学习笔记 2016年6月17日 09:01:19