Java7之多线程 线程的取消与关闭
来源:互联网 发布:centos7 网络配置文件 编辑:程序博客网 时间:2024/05/16 15:53
转载自:http://www.it165.net/pro/html/201402/9239.html
Java没有一种安全的抢占式方法来停止线程,只有一些协作式机制。其中一种协作机制能设置某个“已请求取消”标志,而任务将定期查看该标志。如果设置了这个标志,那么任务将提前结束。举例如下:
01.
public
class
PrimeGenerator
implements
Runnable {
02.
private
static
ExecutorService exec = Executors.newCachedThreadPool();
03.
04.
private
final
List<biginteger> primes =
new
ArrayList<biginteger>();
05.
private
volatile
boolean
cancelled;
// 为了保证可靠,需要volatile类型
06.
07.
public
void
run() {
08.
BigInteger p = BigInteger.ONE;
// 创建一个大整数类型,初始值为1
09.
while
(!cancelled) {
10.
p = p.nextProbablePrime();
11.
synchronized
(
this
) {
// 在添加时要确保同步
12.
primes.add(p);
13.
}
14.
}
15.
}
16.
// 设置取消任务的标识cancelled,以防止搜索素数的线程永远执行下去
17.
public
void
cancel() {
18.
cancelled =
true
;
19.
}
20.
// 获取已经计算出来的素数
21.
public
synchronized
List<biginteger> get() {
// 对ArrayList进行复制,保证正确的遍历
22.
return
new
ArrayList<biginteger>(primes);
23.
}
24.
25.
static
List<biginteger> aSecondOfPrimes()
throws
InterruptedException {
26.
PrimeGenerator generator =
new
PrimeGenerator();
27.
exec.execute(generator);
// 执行这个任务
28.
try
{
29.
SECONDS.sleep(
1
);
30.
}
finally
{
31.
generator.cancel();
// 确保在调用sleep时被中断也能取消素数生成器的任务
32.
}
33.
return
generator.get();
34.
}
35.
}</biginteger></biginteger></biginteger></biginteger></biginteger>
PrimeGenerator使用了一种简单的取消策略:客户代码通过调用cancel来请求取消,PrimeGenerator在每次搜索素数前首先检查是否存在取消请求,如果存在则退出。
如果使用这种策略来请求取消,那么当任务调用了一个阻塞方法的时候,可能任何永远不会检查取消标志,因此永远不会结束。如下举例:
01.
class
BrokenPrimeProducer
extends
Thread {
02.
private
final
BlockingQueue<biginteger> queue;
// 阻塞队列
03.
private
volatile
boolean
cancelled =
false
;
04.
05.
BrokenPrimeProducer(BlockingQueue<biginteger> queue) {
06.
this
.queue = queue;
07.
}
08.
09.
public
void
run() {
10.
try
{
11.
BigInteger p = BigInteger.ONE;
12.
while
(!cancelled)
13.
queue.put(p = p.nextProbablePrime());
14.
}
catch
(InterruptedException consumed) {
15.
}
16.
}
17.
18.
public
void
cancel() {
19.
cancelled =
true
;
20.
}
21.
}
22.
</biginteger></biginteger>
当生产者将队列添满时,消费者希望取消这个任务。但是由于生产者此时处于阻塞状态,那么cancelled标志将得不到检查,生产者不能从阻塞的方法中恢复过来。
线程中断是一种协作机制,每个线程都有一个boolean类型的中断状态。在Thread类中提供了3个中断方法,如下:
1.
public
void
interrupt();
// 中断目标线程
2.
public
boolean
isInterrupted();
// 返回目标线程的中断状态
3.
public
static
boolean
interrupted();
// 清除当前线程的中断状态,并返回它之前的值。也是清除中断状态的唯一方法
(1)interrupt()方法
对于阻塞库方法,如wait、join、sleep方法,都会检查线程何时中断,并且在发现中断时提前返回。调用这个方法会引起这个线程的interrupt状态被清空(设为false),并且会抛出InterruptedException,表示阻塞操作由于中断而提前结束。
当线程在非阻塞状态下中断时,中断状态将被设置。
(2)isInterrupted()方法
这个方法的源代码如下:
1.
public
boolean
isInterrupted() {
2.
return
isInterrupted(
false
);
3.
}
4.
private
native
boolean
isInterrupted(
boolean
ClearInterrupted);
返回这个线程是否被interrupt了,调用这个方法不会影响这个线程的interrupt状态
(3)interrupted()方法
来看这个方法的源代码,如下:
1.
public
static
boolean
interrupted() {
2.
return
currentThread().isInterrupted(
true
);
3.
}
4.
private
native
boolean
isInterrupted(
boolean
ClearInterrupted);
调用这个方法会返回当前线程的interrupt状态(true或false),并把当前线程的interrupt状态清空(设为false)。如果在调用的时候返回true,那么除非你想屏蔽这个中断,否则必须对它进行处理 - 可以抛出InterruptedException,或者通过再次调用interrupt()来恢复中断状态。
注意:这个是个静态方法,并且返回的是当前线程状态,并不一定是调用者的线程状态。
使用这几个方法可以解决如上的自定义取消机制与可阻塞的库函数之间交互的问题,如下:
01.
public
class
PrimeProducer
extends
Thread {
02.
private
final
BlockingQueue<biginteger> queue;
03.
04.
PrimeProducer(BlockingQueue<biginteger> queue) {
05.
this
.queue = queue;
06.
}
07.
08.
public
void
run() {
09.
try
{
10.
BigInteger p = BigInteger.ONE;
11.
while
(!Thread.currentThread().isInterrupted())
// 在在启动寻找素数前进行检测
12.
queue.put(p = p.nextProbablePrime());
13.
}
catch
(InterruptedException consumed) {
14.
/* Allow thread to exit */
15.
}
16.
}
17.
18.
public
void
cancel() {
19.
interrupt();
20.
}
21.
}</biginteger></biginteger>
- Java7之多线程 线程的取消与关闭
- Java 7之多线程 - 线程的取消与关闭
- Java线程的取消与关闭
- Java 多线程 - 线程的取消与关闭
- java线程的取消与关闭
- Java7之多线程读写锁
- java线程取消与关闭
- java线程取消与关闭
- 线程的取消和关闭
- Java并发编程实战 之 线程的取消与关闭
- 线程的创建与取消
- Java7之多线程第8篇 互斥锁ReentrantLock
- Java7之多线程第8篇 互斥锁ReentrantLock
- C++自学笔记之多线程的创建与线程同步
- 线程取消与清理
- 线程的取消/撤销
- 线程的取消模式
- 取消线程的执行
- # 会员注册与登录模块
- 架构师给程序员的一封信
- GEC210(S5PV210)裸机驱动之LCD(1)
- 一个在别人网站扒的tools.js
- Geohash算法
- Java7之多线程 线程的取消与关闭
- hibernate中mysql的ID注解
- 手机卫士学习09-自定义对话框
- 西门子PLC学习笔记十三-(算术运算指令与控制指令)
- 博客新加入“扫码阅读”功能
- Java7之多线程读写锁
- HTML4标签的默认样式列表
- LeetCode--Spiral Matrix
- 在Xcode里面连接MySQL,同时显示出mysql里的数据