不可中断的阻塞:
- Java.io 包中的同步 Socket/IO。 在服务器应用程序中,最常见的阻塞I/O形式就是对套接字进行读取和写入。虽然InputStream和OutputStream中的read和write等方法都不会响应中断,但通过关闭底层的套接字,可以使得由于执行read或write等方法而被阻塞的线程抛出一个SocketException。
- Java.io包中的同步I/O。 当中断一个正在InterruptibleChannel上等待的线程时,将抛出ClosedByInterruptException并关闭链路(这还会使得其他在这条链路上阻塞的线程同样抛出ClosedByInterruptException)。当关闭一个InterruptibleChannel时,将导致所有在链路操作上阻塞的线程都抛出AsynchronousCloseException。大多数标准的Channel都实现了InterruptibleChannel。
- Selector的异步I/O。 如果一个线程在调用Selector.select方法(在java.nio.channels中)时阻塞了,那么调用close或wakeup方法会使线程抛出ClosedSelectorException并提前返回。
- 获取某个锁。 如果一个线程由于等待某个内置锁而阻塞,那么将无法响应中断,因为线程认为它肯定会获得锁,所以将不会理会中断请求。但是,在Lock类中提供了lockInterruptibly方法,该方法允许在等待一个锁的同时仍能响应中断。
通过改写interrupt方法将非标准的取消操作封装在Thread中
public class ReaderThread extends Thread {
private static final int BUFSZ = 2048;
private final Socket socket;
private final InputStream in;
public ReaderThread(Socket socket) throws IOException{
this.socket = socket;
this.in = socket.getInputStream();
}
@Override
public void interrupt() {
try{
socket.close();
}catch(IOException ignored)
{
}finally{
super.interrupt();
}
}
@Override
public void run() {
try {
byte[] buf = new byte[BUFSZ];
while(true){
int count = in.read(buf);
if(count<0)
break;
else if(count>0){
processBuffer(buf,count);
}
}
} catch (IOException e) {
/* 允许线程退出 */
}
}
private void processBuffer(byte[] buf, int count) {
// TODO Auto-generated method stub
}
}
通过newTaskFor将非标准的取消操作封装在一个任务中
public interface CancellableTask<T> extends Callable<T>{
void cancel();
RunnableFuture<T> newTask();
}
@ThreadSafe
public class CancellingExecutor extends ThreadPoolExecutor{
...
protected<T> RunnableFuture<T> newTaskFor(Callable<T> callable){
if(callable instanceof CancellableTask)
return ((CancellableTask<T>) callable).newTask();
else
return super.newTaskFor(callable);
}
}
public abstract class SocketUsingTask<T> implements CancellableTask<T>{
@GuardedBy("this") private Socket socket;
protected synchronized void setSocket(Socket s){
socket = s;
}
public synchronized void cancel(){
try{
if(socket != null)
socket.close();
}catch(IOException ignored){}
}
public RunnableFuture<T> newTask(){
return new FutureTask<T>(this){
public boolean cancel(boolean mayInterruptIfRunning){
try{
SocketUsingTask.this.cancel();
}finally{
return super.cancel(mayInterruptIfRunning);
}
}
};
}
}