美文网首页
Java NIO线程的中断机制

Java NIO线程的中断机制

作者: Monica2333 | 来源:发表于2018-10-25 15:02 被阅读0次

Java NIO中InterruptibleChannel接口表示通道IO阻塞时可被异步的关闭和中断。

public interface InterruptibleChannel extends Channel{

    /**
     * Closes this channel.
     *
     *  Any thread currently blocked in an I/O operation upon this channel
     * will receive an AsynchronousCloseException.
     * throws  IOException  If an I/O error occurs
     */
    public void close() throws IOException;
}

AbstractInterruptibleChannel实现了InterruptibleChannel接口,并提供了实现可中断IO机制的重要的方法,比如begin(),end()。在调用IO操作时,需要如此调用才可实现中断:

try {
     begin();
     completed = ...;    // Perform blocking I/O operation
     return ...;         // Return result
  } finally {
     end(completed);
  }

completed参数说明I/O操作是不是真的完成。比如在read操作中,只有completed返回true,才真的表示读到了buffer中一些数据。
在具体的可中断channel中,如FileChannel,SocketChannel,DatagramChannel必须实现implCloseChannel方法,因为这是表示当前channel中断时希望做哪些操作的回调函数。

begin方法:
在io操作的开始之前负责添加Channel的中断处理器到当前线程

 // -- Interruption machinery,持有中断对象 --
    private Interruptible interruptor;
//持有实现中断机制的线程对象
    private volatile Thread interrupted;
    protected final void begin() {
//实例化中断处理对象,
//标记被中断的线程,并回调implCloseChannel,关闭channel
        if (interruptor == null) {
            interruptor = new Interruptible() {
                    public void interrupt(Thread target) {
                        synchronized (closeLock) {
                        //如果当前channel已被关闭,则直接返回
                            if (!open)
                                return;
                          //设置标志位,登记被中断的线程
                            open = false;
                            interrupted = target;
                            try {
                              //调用具体的实现关闭当前channel
                                AbstractInterruptibleChannel.this.implCloseChannel();
                            } catch (IOException x) { }
                        }
                    }};
        }
      //登记当前线程(当前channel)的中断处理对象
        blockedOn(interruptor);
        Thread me = Thread.currentThread();
      //判断当前线程是不是已经被中断,如果被中断,则手动触发中断操作,关闭channel
        if (me.isInterrupted())
            interruptor.interrupt(me);
    }

可见,nio的channel中断操作,是通过挂载 Interruptible自定义的中断处理对象,当当前线程被中断时,通过回调关闭channel的函数:implCloseChannel,从而实现对当前线程中断的响应。
当前线程如何绑定中断机制对象?看下blockedOn的实现:

// -- sun.misc.SharedSecrets --
    static void blockedOn(Interruptible intr) {         // package-private
        sun.misc.SharedSecrets.getJavaLangAccess().blockedOn(Thread.currentThread(), intr);
    }

通过JavaLangAccess类将当前线程的blocker设置为interruptor。

当Thread在中断时,如何调用nio的中断处理器?

public void interrupt() {
        if (this != Thread.currentThread())
            checkAccess();

        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
              //nio中断处理逻辑
                interrupt0();           // Just to set the interrupt flag
                b.interrupt(this); //调用中断处理器的中断方法
                return;
            }
        }
    //普通流程,仅设置中断处理标志
        interrupt0();
    }

end 方法:

 protected final void end(boolean completed)
        throws AsynchronousCloseException {
      //释放当前线程的处理器引用,避免线程一直存活无法回收掉中断处理器
        blockedOn(null);
        Thread interrupted = this.interrupted;
        if (interrupted != null && interrupted == Thread.currentThread()) {
        //如果当前线程被中断,则抛出ClosedByInterruptException异常,表示Channel因为线程中断而被关闭了,IO操作也随之中断了。
            interrupted = null;
            throw new ClosedByInterruptException();
        }
        if (!completed && !open){
        //当前线程发现Channel被关闭了,并且是读取还未执行完毕的情况,则抛出AsynchronousCloseException异常,表示Channel被异步关闭了。
            throw new AsynchronousCloseException();
    }

如果手动实现一个可中断的channel时,手动处理中断应该是:

this.outstream = Channels.newChannel(outstream);
try {
    outstream.write(message);
}
catch(AsynchronousCloseException e) {
    System.out.println("Another thread closed the stream while this one was blocking on I/O!");
}
catch(ClosedByInterruptException e) {
    System.out.println("This thread has been interrupted while blocking on I/O!");
}

参考资料:
http://www.importnew.com/29430.html
https://stackoverflow.com/questions/10087914/how-do-i-use-interruptiblechannel

相关文章

  • Java NIO线程的中断机制

    Java NIO中InterruptibleChannel接口表示通道IO阻塞时可被异步的关闭和中断。 Abstr...

  • 【多线程】——3.线程的中断

    线程中断的概念 java线程中断是一种协作机制 通过中断并不能直接终止线程的运行 需要被中断的线程自己处理中断 (...

  • 线程中断

    Java的中断是一种协作机制,线程中断不会终止线程的运行,但是可以通过线程中断来实现终止线程运行。 线程在不同状态...

  • 线程中断

    什么是线程中断 Java中断机制是一种协作机制,也就是说通过中断并不能直接终止另一个线程,而需要被中断的线程自己处...

  • Java线程中断机制

    线程中断机制 线程中断是个技术活,1.1版本的stop、resume和suspend方法,分别对应线程暂停、再利用...

  • java线程中断机制

    9.如何中断一个运行中的线程 中断机制是如何工作的?捕获或检测到中断后,是抛出 InterruptedExcept...

  • Java线程的中断

    引言 Java没有提供任何机制来安全地终止线程,但提供了中断机制,即thread.interrupt()方法。线程...

  • Java线程中断机制概述

    Java 没有提供一种安全,直接的方式来停止某个线程,而是提供了中断机制。中断机制是一种协作机制,也就是说通常中断...

  • Java线程Thread之interrupt中断解析

    这一篇我们说说Java线程Thread的interrupt中断机制。 interrupt之中断状态标记 inter...

  • 一种强制关闭线程的方法

    在Java中,停止一个线程的主要机制是中断,中断并不是强迫终止一个线程,它是一种协作机制,是给线程传递一个取消信号...

网友评论

      本文标题:Java NIO线程的中断机制

      本文链接:https://www.haomeiwen.com/subject/yjpqtqtx.html