`
jnullpointer
  • 浏览: 15822 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

NIO包的AbstractInterruptibleChannel分析

阅读更多
这两天重新看了一下java.nio.channels.spi.AbstractInterruptibleChannel的代码,感觉又有一些收获,记录一下。AbstractInterruptibleChannel实现了InterruptibleChannel接口。InterruptibleChannel接口的描述非常重要,直接影响AbstractInterruptibleChannel的行为:
A channel that implements this interface is asynchronously closeable: If a thread is blocked in an I/O operation on an interruptible channel then another thread may invoke the channel's close method. This will cause the blocked thread to receive an AsynchronousCloseException. 

A channel that implements this interface is also interruptible: If a thread is blocked in an I/O operation on an interruptible channel then another thread may invoke the blocked thread's interrupt method. This will cause the channel to be closed, the blocked thread to receive a ClosedByInterruptException, and the blocked thread's interrupt status to be set


说明了两种异常情形:
1.如果线程在channel上阻塞,另外一个线程调用了channel的close方法,会导致阻塞在channel上的线程接收到一个AsynchronousCloseException。
2.如果线程在channel上阻塞,另外一个线程调用该线程的interrupt方法,会导致channel关闭,阻塞的线程接收到ClosedByInterruptException。

这实际上定义了channel上的线程的中断、channel关闭之间关系,基本的意思是:
1.阻塞线程中断->channel关闭,抛出ClosedByInterruptException;
2.channel关闭->阻塞线程抛出AsynchronousCloseException;

AbstractInterruptibleChannel定义了调用模式:
  boolean completed = false;
  try {
      begin();
      completed = ...;    // Perform blocking I/O operation
      return ...;         // Return result
  } finally {
      end(completed);

这个模式主要作用就是finally的end方法一定会执行。

1.先看看ClosedByInterruptException的情形
怎么实现线程中断时关闭channel呢?
不能指望调用者调用thread.interrupt()后,紧跟着再调用channel.close()。
能够想到的办法就是将channel的close方法放到thread.interrupt方法中,JDK就是这么做的,我揣测为了实现这个功能,专门修改thread的方法,为此还引入了变量:
  private volatile Interruptible blocker

在上面的begin方法中,为当前线程植入了一个中断触发器Interruptible,
protected final void begin() {
    if (interruptor == null) {
        interruptor = new Interruptible() {
            public void interrupt() {
                synchronized (closeLock) {
	           if (!open)
		      return;
		   interrupted = true;
	            open = false;
		   try {
		        AbstractInterruptibleChannel.this.implCloseChannel();
	            } catch (IOException x) { }
		}
             }};
	}
    blockedOn(interruptor);
    if (Thread.currentThread().isInterrupted())
        interruptor.interrupt();
}

这个Interruptible回调AbstractInterruptibleChannel的关闭方法
  AbstractInterruptibleChannel.this.implCloseChannel()

当然,Thread的interrupt方法也要修改,当调用thread.interrupt方法时,如果中断触发器不为空,便会调用触发器的方法。
public void interrupt() {
    if (this != Thread.currentThread())
        checkAccess();

    synchronized (blockerLock) {
        Interruptible b = blocker;
        if (b != null) {
            interrupt0();           
            b.interrupt();
            return;
        }
    }
    interrupt0();
}

上面的这几处就实现了线程中断时,会调用channel的close方法。将这两个动作绑定在一起。
在上面的end方法中,会调用blockedOn(null)将中断触发器清空。
protected final void end(boolean completed) throws AsynchronousCloseException{
    blockedOn(null);
    if (completed) {
        interrupted = false;
        return;
    }
    if (interrupted) throw new ClosedByInterruptException();
    if (!open) throw new AsynchronousCloseException();
}

整体过程是:
1.线程执行begin方法,植入中断触发器,然后可能在channel上阻塞;
2.另外一个线程调用步骤1线程的interrupt方法;
3.interrupt方法会执行channel的close方法,并设置标志位interrupted = true;
4.线程进入end方法,清空线程的中断触发器,当判断interrupted = true时,抛出ClosedByInterruptException。

2.先看看AsynchronousCloseException的情形
当一个线程阻塞在channel上,另外一个线程调用channel的close方法,怎么实现阻塞线程抛出异常呢?难点在于channel的close方法必须通知阻塞的线程,让它中断。
拔了一下代码,大致理清了过程。
实现类AbstractSelectableChannel的implCloseChannel方法会调用implCloseSelectableChannel方法。这个抽象方法的实现类有多个,比如sun.nio.ch.ServerSocketChannelImpl的implCloseSelectableChannel实现
    protected void implCloseSelectableChannel() throws IOException {
        synchronized (stateLock) {
            nd.preClose(fd);
            long th = thread;
            if (th != 0)
                NativeThread.signal(th);
            if (!isRegistered())
                kill();
        }
    }

可以看到NativeThread.signal执行通知线程中断。thread来自于accept方法
  public SocketChannel accept() throws IOException {
      ...
      thread = NativeThread.current();
      ...

NativeThread.signal是native方法,在NativeThread.c中看到相应的实现:
  Java_sun_nio_ch_NativeThread_signal(JNIEnv *env, jclass cl, jlong thread)
{
#ifdef __linux__
    if (pthread_kill((pthread_t)thread, INTERRUPT_SIGNAL))
        JNU_ThrowIOExceptionWithLastError(env, "Thread signal failed");
#endif
}

俺不懂C,但大致能看出对线程执行中断操作。
整个过程如下:
1.某个线程执行了channel的close方法;
2.channel的会调用操作系统函数对阻塞的线程发出中断指令;
3.阻塞线程执行end方法,此时的interrupted=false,这个值只有执行interruptor.interrupt()方法时才会置为true,所以不会抛出ClosedByInterruptException。
4.此时open = false,抛出AsynchronousCloseException异常。

通过上面的分析,有几点收获
1.如果想在线程中断时执行一些操作,中断触发器是一个很好的钩子;
2.windows平台的windows\classes\sun\nio\ch\NativeThread.java中,current方法和signal方法都是空实现。所以不太明白windows平台上,channel的close方法如何通知阻塞线程中断的。
class NativeThread {
    static long current() { return -1; }
    static void signal(long nt) { }
}

3.channel的实现类中保存了thread的ID,是不是一个channel某个时间点上只能对应一个线程来操作?
分享到:
评论

相关推荐

    java NIO.zip

    Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java标准库提供的一种替代传统的I/O模型的新技术。自Java 1.4版本引入NIO后,它为Java开发者提供了更高效的数据传输方式,尤其是在处理大量并发...

    java nio 包读取超大数据文件

    ### Java NIO 处理超大数据文件的知识点详解 #### 一、Java NIO简介 Java NIO(New IO)是Java平台上的新输入/输出流API,它提供了与传统IO(即Java IO)不同的数据处理方式。NIO在Java 1.4版本引入,并在后续版本...

    java org.apache.http.nio jar包

    找了好久,终于找到了,java刷新同步获取网络资源

    Android开发进阶之NIO非阻塞包

    ### Android开发进阶之NIO非阻塞包 #### NIO非阻塞通讯方式解析 在探讨Android DDMS源码中的NIO(Non-blocking I/O)非阻塞通讯方式时,我们首先需要理解NIO的基本概念及其在Android开发中的应用。 **NIO简介**:...

    Java NIO原理 图文分析及代码实现

    ### Java NIO原理 图文分析及代码实现 #### 前言 在深入探讨Java NIO之前,我们先简要回顾一下NIO的概念及其引入的原因。随着互联网的发展,越来越多的应用程序需要处理高并发的网络连接请求。传统的阻塞I/O模型在...

    Java.NIO资源下载资源下载

    根据提供的文件信息,我们可以提取并总结出关于Java NIO(New Input/Output)的重要知识点。 ### Java NIO 概述 Java NIO 是 Java 平台的一个重要特性,首次出现在 Java 1.4 版本中。它为 Java 开发者提供了一套...

    Java NIO——Selector机制解析三(源码分析)

    本文将深入探讨Java NIO中的Selector机制,并通过源码分析来理解其实现原理。 Selector机制是Java NIO中的核心组件,它允许单线程同时监控多个通道(Channels)的状态变化,例如连接就绪、数据可读或可写等。这种...

    httpcore-nio-4.3.jar包

    6. **案例分析与实战** 通过实例演示如何使用HttpCore NIO创建服务器和客户端,以及如何处理HTTP请求和响应,展示其实用性和灵活性。 7. **与其他框架的集成** HttpCore NIO可以与许多其他Java Web框架无缝集成,...

    mina框架--MINA框架是对java的NIO包的一个封装

    MINA(Multipurpose Infrastructure for Network Applications)框架是Apache软件基金会的一个开源项目,它提供了一种高级的、事件驱动的网络应用程序框架,用于简化基于Java的网络编程,特别是使用非...,简称NIO)...

    jdk1.6 源码 包含nio等

    在JDK 1.6的源码中,你可以深入理解这些概念的实现细节,例如`java.nio`包下的各种类和接口,以及`sun.nio`包中的实现类,这些都是NIO核心功能的实现。`launcher`可能是JVM的启动器,`org`、`javax`、`java`、`com`...

    高性能网络编程必备技能之IO与NIO阻塞分析

    本文将重点探讨Java中的IO(Input/Output)和NIO(Non-blocking I/O)模型,以及它们在处理阻塞问题上的差异。 IO模型在Java中是基于流的,它主要通过`InputStream`和`OutputStream`接口及其子类来实现数据的读写。...

    Java NIO原理分析及代码实例

    Java NIO(New IO)是Java 1.4版本引入的一个新API,全称为Non-blocking Input/Output,它提供了一种不同于传统IO的编程模型,传统IO基于块I/O,而NIO则基于通道(Channel)和缓冲区(Buffer)进行数据传输。NIO的...

    Java NIO 中文版.rar

    Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java标准库提供的一种替代传统I/O模型的新技术。在Java 1.4版本中引入,NIO为开发者提供了更加灵活和高效的I/O操作方式,特别是在处理高并发、大...

    Java NIO与IO性能对比分析.pdf

    本文将分析Java NIO与Java IO在性能上的对比,并尝试找出性能差异的原因,以及探讨哪种编程模型更适合高并发的应用场景。 Java IO模型是一种阻塞型I/O模型,在数据的读写过程中,如果线程在等待数据,将会一直被挂...

    Java语言基础教程-Java NIO流篇1

    Java NIO(New Input/Output)是Java标准库中提供的一种I/O模型,与传统的BIO(Block I/O)模型不同,NIO提供了更高效的数据处理方式,特别适合于高并发、大数据量的网络应用。在Java NIO流篇1的学习中,我们将深入...

    Java-NIO非阻塞服务器示例.docx

    本资源主要讲解了Java-NIO非阻塞服务器的示例,通过使用Java-NIO包来实现非阻塞的服务器端模式。下面是从代码中提取的知识点: 一、Java-NIO包简介 Java-NIO(New I/O)包是Java 1.4版本中引入的新IO处理机制,...

    httpcore-nio-4.4.5-API文档-中文版.zip

    赠送jar包:httpcore-nio-4.4.5.jar; 赠送原API文档:httpcore-nio-4.4.5-javadoc.jar; 赠送源代码:httpcore-nio-4.4.5-sources.jar; 赠送Maven依赖信息文件:httpcore-nio-4.4.5.pom; 包含翻译后的API文档:...

    xnio-nio-3.8.0.Final-API文档-中文版.zip

    赠送jar包:xnio-nio-3.8.0.Final.jar; 赠送原API文档:xnio-nio-3.8.0.Final-javadoc.jar; 赠送源代码:xnio-nio-3.8.0.Final-sources.jar; 赠送Maven依赖信息文件:xnio-nio-3.8.0.Final.pom; 包含翻译后的API...

    基于事件的NIO多线程服务器打包

    该包封装过的NIO比sun本身的更容易处理 server中只有区区几行就搞定了: //创建listener TimeHandler timer = new TimeHandler(); //获取Notifier Notifier notifier = Notifier.getNotifier(); //注册监听 notifier....

    java nio

    Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java从1.4版本开始引入的一种I/O模型,旨在提供一种更高效、更具弹性的I/O处理方式。NIO与传统的BIO(Blocking I/O)模式相比,主要区别在于对I/O...

Global site tag (gtag.js) - Google Analytics