这两天重新看了一下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,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java标准库提供的一种替代传统的I/O模型的新技术。自Java 1.4版本引入NIO后,它为Java开发者提供了更高效的数据传输方式,尤其是在处理大量并发...
### Java NIO 处理超大数据文件的知识点详解 #### 一、Java NIO简介 Java NIO(New IO)是Java平台上的新输入/输出流API,它提供了与传统IO(即Java IO)不同的数据处理方式。NIO在Java 1.4版本引入,并在后续版本...
找了好久,终于找到了,java刷新同步获取网络资源
### Android开发进阶之NIO非阻塞包 #### NIO非阻塞通讯方式解析 在探讨Android DDMS源码中的NIO(Non-blocking I/O)非阻塞通讯方式时,我们首先需要理解NIO的基本概念及其在Android开发中的应用。 **NIO简介**:...
### Java NIO原理 图文分析及代码实现 #### 前言 在深入探讨Java NIO之前,我们先简要回顾一下NIO的概念及其引入的原因。随着互联网的发展,越来越多的应用程序需要处理高并发的网络连接请求。传统的阻塞I/O模型在...
根据提供的文件信息,我们可以提取并总结出关于Java NIO(New Input/Output)的重要知识点。 ### Java NIO 概述 Java NIO 是 Java 平台的一个重要特性,首次出现在 Java 1.4 版本中。它为 Java 开发者提供了一套...
本文将深入探讨Java NIO中的Selector机制,并通过源码分析来理解其实现原理。 Selector机制是Java NIO中的核心组件,它允许单线程同时监控多个通道(Channels)的状态变化,例如连接就绪、数据可读或可写等。这种...
6. **案例分析与实战** 通过实例演示如何使用HttpCore NIO创建服务器和客户端,以及如何处理HTTP请求和响应,展示其实用性和灵活性。 7. **与其他框架的集成** HttpCore NIO可以与许多其他Java Web框架无缝集成,...
MINA(Multipurpose Infrastructure for Network Applications)框架是Apache软件基金会的一个开源项目,它提供了一种高级的、事件驱动的网络应用程序框架,用于简化基于Java的网络编程,特别是使用非...,简称NIO)...
在JDK 1.6的源码中,你可以深入理解这些概念的实现细节,例如`java.nio`包下的各种类和接口,以及`sun.nio`包中的实现类,这些都是NIO核心功能的实现。`launcher`可能是JVM的启动器,`org`、`javax`、`java`、`com`...
本文将重点探讨Java中的IO(Input/Output)和NIO(Non-blocking I/O)模型,以及它们在处理阻塞问题上的差异。 IO模型在Java中是基于流的,它主要通过`InputStream`和`OutputStream`接口及其子类来实现数据的读写。...
Java NIO(New IO)是Java 1.4版本引入的一个新API,全称为Non-blocking Input/Output,它提供了一种不同于传统IO的编程模型,传统IO基于块I/O,而NIO则基于通道(Channel)和缓冲区(Buffer)进行数据传输。NIO的...
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java标准库提供的一种替代传统I/O模型的新技术。在Java 1.4版本中引入,NIO为开发者提供了更加灵活和高效的I/O操作方式,特别是在处理高并发、大...
本文将分析Java NIO与Java IO在性能上的对比,并尝试找出性能差异的原因,以及探讨哪种编程模型更适合高并发的应用场景。 Java IO模型是一种阻塞型I/O模型,在数据的读写过程中,如果线程在等待数据,将会一直被挂...
Java NIO(New Input/Output)是Java标准库中提供的一种I/O模型,与传统的BIO(Block I/O)模型不同,NIO提供了更高效的数据处理方式,特别适合于高并发、大数据量的网络应用。在Java NIO流篇1的学习中,我们将深入...
本资源主要讲解了Java-NIO非阻塞服务器的示例,通过使用Java-NIO包来实现非阻塞的服务器端模式。下面是从代码中提取的知识点: 一、Java-NIO包简介 Java-NIO(New I/O)包是Java 1.4版本中引入的新IO处理机制,...
赠送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文档:...
赠送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比sun本身的更容易处理 server中只有区区几行就搞定了: //创建listener TimeHandler timer = new TimeHandler(); //获取Notifier Notifier notifier = Notifier.getNotifier(); //注册监听 notifier....
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java从1.4版本开始引入的一种I/O模型,旨在提供一种更高效、更具弹性的I/O处理方式。NIO与传统的BIO(Blocking I/O)模式相比,主要区别在于对I/O...