Java之前有stop跟suspend方法从外部强制终止跟暂停一个线程。但是这两个方法都存在一个相当严重的问题,因为这样它们都被废弃了。
stop:一个线程被外部强行stop后会解锁所有监视器,导致阻塞该监视器的线程被唤醒。这可能导致被唤醒的线程使用一些状态不完全的对象。因为这些对象本来可能是要在被终止线程进行初始化等操作的。
suspend:该方法能够从外部强行暂停一个线程,但它不会也不应该释放锁,从而可能导致死锁。
随着这两个方法被废弃,Java提供了中断策略来终止一个线程。也就是外部线程可以对目标线程给出一个中断信号,至于如何处理中断交由线程自己决定。所以每一个线程对象都可假想有一个线程中断标志位,中断一般涉及到3个方法:
1. interrupt:该方法设置线程的中断标志位为true。但是它会引发线程调度吗,需要确定? 线程的wait,sleep,join会捕获该状态,抛出InterruptException。
2. isInterrupted:检查线程对象的中断标志
3. interrupted:这是个静态方法,作用同isInterrupted,区别是将中断标志设为false
4. InterruptException:有wait,sleep,join等可中断方法在中断标志位true时抛出,线程捕获该异常后,中断标志自动设为false.
有了上诉方法:可以这样中断一个线程:
-
class ThreadA extends Thread{
-
public void run(){
-
while(!Thread.currentThread().isInterrupted()){
-
try{
-
Thread.sleep(10000); //类似于sleep的可中断方法,如wait等
-
}catch(InterruptedException e){
-
Thread.currentThread().interrupt();
-
}
-
}
-
}
-
}
但是这个方法不通用,因为很多线程不会调用阻塞方法,也有些线程调用的是不可中断的阻塞方法。那么上诉方法就失效了。
一. 没有调用阻塞方法的线程
对于这种情况,通常外部线程是没办法终止该线程了。像以下这种方法:
-
public void run(){
-
while(!Thread.currentThread().isInterrupted() && need more work to do){
-
...
-
}
-
}
该方法问题是调用interrupt时,我们不知道目标线程的状态,不知道它执行到哪里。
二. 不可中断阻塞
一些线程在不可中断的方法阻塞,比如不可中断IO,等待锁等。那么它无法响应中断信号,因为这些阻塞方法不会抛出InterruptException。一个方法捕获这些不可中断IO能抛出的异常,然后显示产生这些异常。比如输入流in.read属于不可中断阻塞,但在read过程中如果in被close则会抛出异常,那么改写interrupt让其调用close是个办法。
对于阻塞于锁对象,synchronized并不支持响应中断。java并发包的lock提供了可中断锁。
阅读(888) | 评论(0) | 转发(0) |