并非所有的可阻塞方法或者阻塞机制都能响应中断,如果一个线程由于执行同步的Socket I/O或者等待获得内置锁而阻塞,那么中断请求只能设置线程的中断状态,除此之外没有其他任何作用,处理这种阻塞时,我们必须知道线程阻塞的原因
1.java.io包中的同步Socket I/O:在服务器应用程序中,最常见的阻塞I/O形式就是对套接字进行读取和写入.虽然InputStream和OutputStream中的read和wirte等方法都不会响应中断但是通过关闭底层的套接字,可以使得由于执行read或write方法而被阻塞的线程抛出一个SocketException
class ReaderThread extends Thread{
private final Socket socket;
private final InputStream in;
public ReaderThread(Socket socket) throws IOException{
this.socket = socket;
this.in = socket.getInputStream();
}
// 重写interrupt方法,使其既能处理标准的中断,也能关闭底层的套接字,因此无论该线程是在read方法中阻塞,
// 还是在某个可中断方法中阻塞,都可以被中断并停止执行当前的工作
@Override
public void interrupt(){
try {
socket.close();
} catch (IOException e) {
// ignored
}finally {
super.interrupt();
}
}
@Override
public void run(){
try {
byte[] buf = new byte[1024];
while (true){
int count = in.read(buf);
if (count< 0 ){
break;
}else {
}
}
} catch (IOException e) {
//todo
}
}
}
2.java.io包中的同步I/O:当中断一个正在InterruptibleChannel上等待的线程时,将抛出ClosedByInterrupException并关闭链路(这还会使得其他在这条链路上阻塞的线程同样抛出ClosedByInterrupException),当关闭一个InterruptibleChannel时,将导致所有在链路操作上阻塞的线程都抛出AsynchronousCloseException,大多数标准的Channel都实现了InterruptibleChannel
3.Selector的异步I/O:如果一个线程在调用Selector.select方法(在java.nio.channels中)时阻塞了,那么调用close或者wakeup方法会使线程抛出ClosedSelectorException并提前返回
4.获取某个锁:当一个线程由于等待某个内置锁而阻塞,那么将无法响应中断,因为线程认为它肯定会获得锁,所以将不会理会中断请求.但是,在Lock类中提供了的lockInterruptibly方法,该方法允许在等待一个锁的同时仍能响应中断