[JDK]从Thread.stop到线程取消

Thread.stop不推荐用了,原因javadoc上给出的链接里面有。大概来讲,是stop会抛出ThreadDeath异常(准确讲是Error),而抛出异常的方法会释放锁(release monitor),其它方法就会访问到本来被锁保护的对象,而这些对象可能处于不一致的状态(没锁保护,但被多线程访问),导致产生不可预知的结果。关键是这种现象很难被观察到,也很难找到原因(根据一个现象,很难发现是stop导致的问题)。很难观察到,是因为它可能有很长的潜伏期,几天之后才会出问题,所谓的“偶发现象”,不能在短时间重现。
所以一般建议改写run方法,将它用while包起来,while里面判断一个(或若干)状态,再写一个cancle方法取消(或停止)线程,这个cancle会简单,改一下状态就行了。

private volatile Thread blinker;

public void stop() {
blinker = null;
}

public void run() {
Thread thisThread = Thread.currentThread();
while (blinker == thisThread) {
try {
thisThread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}

只是要注意一下状态的同步(使用volatile或其它同步方式)
但java并发编程中,大师发现了这种模式的一个问题,如果while中的动作会阻塞,那么while可能很长时间或永远不会退出。

public void run() {
try {
while(!canceled) {
blockingQueue.put(produceLongTimeJob());
}
} catch (InterruptedException ex) {
/* 允许线程退出 */
}
}

使用生产者消费者模式,生产者快于消费者,任务队列已经饱和,再调用阻塞队列的put方法就会阻塞,此时只要消费者没有消费任务,整个工作就不会停止,即使调用了停止方法去更改了canceled的状态。
解决方法java并发编程中也给出了,使用中断。“中断通常是实现取消最明智的选择”。

public void run() {
try {
while(!Thread.currentThread().isInterrupted()) {
blockingQueue.put(produceLongTimeJob());
}
} catch (InterruptedException ex) {
/* 允许线程退出 */
}
}

这种写法只是加快了中断检测,在生产任务之前如果检测到中断就可以直接退出。其实有try,catch检测中断,逻辑上就可以使用中断来退出了。
在concurrent包里面,ThreadExecute的工作线程的run方法就是使用while检查状态

public void run() {
try {
Runnable task = firstTask;
firstTask = null;
while (task != null || (task = getTask()) != null) {
runTask(task);
task = null;
}
} finally {
workerDone(this);
}
}

而在getTask方法中就包括使用中断去通知线程退出

Runnable getTask() {
for (;;) {
try {
int state = runState;
if (state > SHUTDOWN)
return null;
Runnable r;
if (state == SHUTDOWN) // Help drain queue
r = workQueue.poll();
else if (poolSize > corePoolSize || allowCoreThreadTimeOut)
r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS);
else
r = workQueue.take();
if (r != null)
return r;
if (workerCanExit()) {
if (runState >= SHUTDOWN) // Wake up others
interruptIdleWorkers();
return null;
}
// Else retry
} catch (InterruptedException ie) {
// On interruption, re-check runState
}
}
}

interruptIdleWorkers()会中断没做事的工作线程,工程线程检测到中断就会退出。
所以在多线程编程中,一定要处理中断,因为它很常见,而且为了线程能很好的处理退出,也要处理中断,原因上面讲了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值