您的浏览器过于古老 & 陈旧。为了更好的访问体验, 请 升级你的浏览器
Ready 发布于2013年08月17日 10:19

原创 Java nio入门教程详解(十六)

1280 次浏览 读完需要≈ 6 分钟

内容目录

3.1.3 关闭通道

与缓冲区不同,通道不能被重复使用。一个打开的通道即代表与一个特定 I/O 服务的特定连接并封装该连接的状态。当通道关闭时,那个连接会丢失,然后通道将不再连接任何东西。

package java.nio.channels;
public interface Channel
{
public boolean isOpen();
public void close() throws IOException;
}

调用通道的close()方法时,可能会导致在通道关闭底层I/O服务的过程中线程暂时阻塞 ,哪怕该通道处于非阻塞模式。通道关闭时的阻塞行为(如果有的话)是高度取决于操作系统或者文件系统的。在一个通道上多次调用close()方法是没有坏处的,但是如果第一个线程在close()方法中阻塞,那么在它完成关闭通道之前,任何其他调用close()方法都会阻塞。后续在该已关闭的通道上调用close()不会产生任何操作,只会立即返回。

可以通过isOpen()方法来测试通道的开放状态。如果返回true值,那么该通道可以使用。如果返回false值,那么该通道已关闭,不能再被使用。尝试进行任何需要通道处于开放状态作为前提的操作,如读、写等都会导致ClosedChannelException异常。

通道引入了一些与关闭和中断有关的新行为。如果一个通道实现InterruptibleChannel接口(参见图 3-2),它的行为以下述语义为准:如果一个线程在一个通道上被阻塞并且同时被中断(由调用该被阻塞线程的interrupt()方法的另一个线程中断),那么该通道将被关闭,该被阻塞线程也会产生一个ClosedByInterruptException异常。

此外,假如一个线程的interrupt status被设置并且该线程试图访问一个通道,那么这个通道将立即被关闭,同时将抛出相同的ClosedByInterruptException异常。线程的interrupt status 在线程的interrupt()方法被调用时会被设置。我们可以使用isInterrupted()来测试某个线程当前的interrupt status。当前线程的interrupt status可以通过调用静态的Thread.interrupted()方法清除。

Socket通道关闭会花费较长时间,具体时耗取决于操作系统的网络实现。在输出内容被提取时,一些网络协议堆栈可能会阻塞通道的关闭。

请不要将在Channels上休眠的中断线程同在Selectors上休眠的中断线程混淆。前者会关闭通道,而后者则不会。不过,如果您的线程在Selector上休眠时被中断,那它的interrupt status会被设置。假设那个线程接着又访问一个Channel,则该通道会被关闭。关于选择器(Selectors)我们会在第四章中讨论。

仅仅因为休眠在其上的线程被中断就关闭通道,这看起来似乎过于苛刻了。不过这却是NIO架构师们所做出的明确的设计决定。经验表明,想要在所有的操作系统上一致而可靠地处理被中断的 I/O 操作是不可能的。“在全部平台上提供确定的通道行为”这一需求导致了“当 I/O 操作被中断时总是关闭通道”这一设计选择。这个选择被认为是可接受的,因为大部分时候一个线程被中断就是希望以此来关闭通道。java.nio包中强制使用此行为来避免因操作系统独特性而导致的困境,因为该困境对I/O区域而言是极其危险的。这也是为增强健壮性(robustness)而采用的一种经典的权衡。

可中断的通道也是可以异步关闭的。实现InterruptibleChannel接口的通道可以在任何时候被关闭,即使有另一个被阻塞的线程在等待该通道上的一个I/O操作完成。当一个通道被关闭时,休眠在该通道上的所有线程都将被唤醒并接收到一个AsynchronousCloseException异常。接着通道就被关闭并将不再可用。

一开始的NIO版本JDK 1.4.0有几个与中断的通道操作以及异步可关闭性相关的严重缺陷。这些问题期待在 1.4.1 版本中的到解决。在 1.4.0 版本中,当休眠在一个通道 I/O 操作上的线程被阻塞或者该通道被另一个线程关闭时,这些线程也许不能确保都能被唤醒。因此在使用依靠该行为的操作时请务必小心。

不实现InterruptibleChannel接口的通道一般都是不进行底层本地代码实现的有特殊用途的通道。这些也许是永远不会阻塞的特殊用途通道,如旧系统数据流的封装包或不能实现可中断语义的writer类等。(参见 3.7 节)

Java nio入门教程详解(十七)

  • CodePlayer技术交流群1
  • CodePlayer技术交流群2

0 条评论

撰写评论