不可中断的阻塞

并非所有的可阻塞方法或者阻塞机制都能响应中断,如果一个线程由于执行同步的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方法,该方法允许在等待一个锁的同时仍能响应中断

posted @ 2022-05-17 16:26  Kavins  阅读(98)  评论(0编辑  收藏  举报