`
simohayha
  • 浏览: 1395741 次
  • 性别: Icon_minigender_1
  • 来自: 火星
社区版块
存档分类
最新评论

Nonblocking I/O

    博客分类:
  • java
阅读更多
在Nonblocking I/O中最重要的也就是三个类

引用
java.nio.channels.SelectableChannel
java.nio.channels.Selector
java.nio.channels.SelectionKey


1 SelectableChannel

默认情况下channels是阻塞的.我们可以设置一个channel为nonblock的,可是并不是所有的channel都可以设置为nonblock的,比如file channels就不能设置为nonblock.所有提供nonblocking I/O的类都是SelectableChannel的子类.

我们能够通过configureBlocking方法来设置channel为nonblocking mode.

public abstract SelectableChannel configureBlocking(boolean block)
 throws IOException



当你将一个channel置于nonblocking mode时,你就不能立即读或者写它,你需要将它注册到一个Selector对象.也就是说此时这个channel什么时候读和写,已经完全交给这个selector来控制了.

我们使用register方法来注册一个channel到一个Selector对象.

public abstract SelectionKey register(Selector selector, int operations)
 throws ClosedChannelException


这里要注意的是一个channel对象只能被注册到一个Selector对象一次.

register方法的第二个参数指的是这个Selector如何处理这个channel,这里有4中操作方式:
reading, writing, accepting和connecting.其中我们可以用| 来加入多个操作.Server socket channels是accepting.

channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);


register还有一个三个参数的方法
public abstract SelectionKey register(
 Selector selector, int operations, Object attachment)
 throws ClosedChannelException


在这里第三个参数可以为空,如果为空也就相当于2个参数的方法了.这个参数也就是存储一个channel读或者写的数据.一般都使用一个ByteBuffer对象来存储这个.

register返回一个SelectionKey对象,来表示这个channel与Selector的对象之间的独一无二的关系.

register和configureBlocking都是线程安全的.

其他的方法,去看jdk文档就行了.

2 Selector

Selector类可以说是nonblocking I/O中最重要的一个类.因为他能够控制你的程序中的channel什么时候准备好被存取.我们能够使用它的静态方法open来创建一个 Selector对象:

public static Selector open( ) throws IOException


当你想要得到Selector那些channel准备好了的时候,也就是说那些channel能够非阻塞的读或者写.你可以调用下面的三个方法中的一个:

public abstract int selectNow( ) throws IOException
public abstract int select( ) throws IOException
public abstract int select(long timeout) throws IOException


selectNow方法是非阻塞的,而另外两个方法是阻塞的.selectNow方法将会马上返回,哪怕它并没有select到任何东西.而另外两个方法则是select到了channel才会返回,或者线程中断,或者超时也会返回.

其实这3个方法说白了,也就是选择出一个准备好io操作的channel的集合.返回值就是准备好的channel的个数.

还有一个方法selectedKeys,返回一个java.util.Set ,这个set里面包含所有注册在这个Selector上的准备好io操作的channel的key.

 public abstract Set<SelectionKey> selectedKeys();



这里要注意,一个Selector,当你使用完他时应当调用他的close方法来关闭它:
public abstract void close( ) throws IOException


在一些系统里,一个select()可能会阻塞一个线程一段时间,此时另外的线程能够调用Selector's wakeup方法来使select方法立即返回.jdk文档里是这样写的:

引用
If another thread is currently blocked in an invocation of the select() or select(long) methods then that invocation will return immediately. If no selection operation is currently in progress then the next invocation of one of these methods will return immediately unless the selectNow() method is invoked in the meantime. In any case the value returned by that invocation may be non-zero. Subsequent invocations of the select() or select(long) methods will block as usual unless this method is invoked again in the meantime.


3 SelectionKey

java.nio.channels.SelectionKey 封装了一个channel注册到一个Selector上的所有信息 每一个SelectionKey封装了下列的信息:

引用
The channel

The Selector

An arbitrary object attachment, normally used to point to the data the channel is reading or writing

The operations the channels is interested in performing

The operations the channel is currently ready to perform without blocking (or, more accurately, was ready to perform when select( ) was last called)


这些信息在SelectionKey中大部分都是通过set或者get方法来进行设置和得到的.

readyOps方法可以得到这个SelectionKey的mode,也就是说,得到它是read, write, connect, 还是accept.

public abstract int readyOps( )


这里还有一套更方便的api来判断这个:

public final boolean isReadable( )
public final boolean isWritable( )
public final boolean isConnectable( )
public final boolean isAcceptable( )


如果你想读或者写channel,你必须得通过channel方法来得到这个channel然后才能进行操作.

public abstract SelectableChannel channel( )



这里要注意一个channel能有多个key,但是每一个key只能有一个channel.

这里还有两个重要的方法:

public final Object attach(Object ob)
public final Object attachment( )


第一个方法attach联系这个对象到这个key(或者用三个参数的register方法也是一样的),第二个方法attachment是从key中得到这个对象.

你还能通过cancel方法来撤销一个注册:

public abstract void cancel( )


这边有一个简单的例子:


import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;


public class NonBlockDataStuffer {
	private static byte[] data = new byte[256];

	public static void main(String[] args) throws IOException {
		for (int i = 0; i < data.length; i++)
			data[i] = (byte) i;
		ServerSocketChannel server = ServerSocketChannel.open();
		server.configureBlocking(false);
	    server.socket().bind(new InetSocketAddress(9000));
	    Selector selector = Selector.open( );
	    ByteBuffer buffer=ByteBuffer.allocate(256);
	    server.register(selector, SelectionKey.OP_ACCEPT,buffer);
		while (true) {
			selector.select();
			Set<SelectionKey> readyKeys = selector.selectedKeys( );
		    Iterator<SelectionKey> iterator = readyKeys.iterator( );
			while (iterator.hasNext( )) {
		        SelectionKey key = iterator.next( );
		        iterator.remove();
		        try {
		          if (key.isAcceptable()) {
		            SocketChannel client = server.accept();
		            System.out.println("Accepted connection from " + client);
		            client.configureBlocking(false);
		            ByteBuffer source = ByteBuffer.wrap(data);
		            SelectionKey key2 = client.register(selector, SelectionKey.OP_WRITE);
		            key2.attach(source);
		          }
		          else if (key.isWritable( )) {
		            SocketChannel client = (SocketChannel) key.channel( );
		            ByteBuffer output = (ByteBuffer) key.attachment();
		            if (!output.hasRemaining( )) {
		              output.rewind( );
		            }
		            client.write(output);
		          }
		        }
		        catch (IOException ex) {
		          key.cancel( );
		          selector.close();
		          try {
		            key.channel().close();
		          }
		          catch (IOException cex) {}
		        }
		      }

		}
	}
}


其实nio还有一个很重要的类那就是pipe,那个下次再说了...






















5
3
分享到:
评论
1 楼 congpeixue 2008-04-07  
引用

public abstract int selectNow( ) throws IOException
public abstract int select( ) throws IOException
public abstract int select(long timeout) throws IOException

selectNow方法是非阻塞的,而另外两个方法是阻塞的.selectNow方法将会马上返回,哪怕它并没有select到任何东西.而另外两个方法则是select到了channel才会返回,或者线程中断,或者超时也会返回.

不是太明白, Selector是非阻塞的,这里的方法怎么又有阻塞和非阻塞之分呢,楼主有空给讲解下吧。

相关推荐

    Linux系统中网络I_O性能改进方法的研究.pdf

    2. **非阻塞模式(Nonblocking I/O)** 非阻塞模式避免了阻塞模式中的进程等待。当应用程序尝试读取或写入时,如果数据不可用,内核会立即返回一个错误,而不是挂起进程。应用需要持续轮询检查数据是否就绪,这种...

    Using TCP Through Sockets.pdf

    Section three describes the use of nonblocking I/O to improve performance and presents, as an example, an asynchronous finger client. Finally, a library that simplifies the use of asynchronous ...

    [Java] Java 网络编程 第4版 (英文版)

    Manage many connections at the same time with the nonblocking I/O ☆ 出版信息:☆ [作者信息] Elliotte Rusty Harold [出版机构] 奥莱理 [出版日期] 2013年10月14日 [图书页数] 502页 [图书语言] 英语 ...

    Netty面试题(2020最新版).pdf

    Netty基于NIO(Nonblocking I/O,非阻塞IO),封装了JDK的NIO,让开发者使用起来更加灵活。 Netty的特点包括: * 高并发:Netty基于NIO开发,具有高并发性能。 * 传输快:Netty的传输依赖于零拷贝特性,减少了内存...

    UNIX环境高级编程英文第三版+源码

    16.8 Nonblocking and Asynchronous I/O 627 16.9 Summary 628 Chapter 17. Advanced IPC 629 17.1 Introduction 629 17.2 UNIX Domain Sockets 629 17.2.1 Naming UNIX Domain Sockets 634 17.3 Unique Connections...

    UNIX环境高级编程(第二版,英文版)

    Alternatives to Standard I/O Section 5.15. Summary Exercises Chapter 6. System Data Files and Information Section 6.1. Introduction Section 6.2. Password File Section 6.3...

    Netty 20道面试题和答案.docx

    Netty 是一款基于 NIO(Nonblocking I/O,非阻塞 IO)开发的网络通信框架,对比于 BIO(Blocking I/O,阻塞 IO),他的并发性能得到了很大提高。难能可贵的是,在保证快速和易用性的同时,并没有丧失可维护性和性能...

    UNIX Network Programming Volume 1, Third Edition (Unix网络编程卷1第3版英文版)

    I/O Multiplexing: The select and poll Functions Section 6.1. Introduction Section 6.2. I/O Models Section 6.3. select Function Section 6.4. str_cli Function (Revisited) Section 6.5. Batch ...

    nonblocking async transfer server

    它利用了非阻塞I/O模型,使得服务器在等待数据读写时不会被挂起,而是立即返回处理其他任务,从而提高了效率。异步传输进一步增强了这一特性,服务器在发起请求后无需等待响应,而是可以继续处理其他请求,当数据...

    Java NIO核心概念总结篇

    Java NIO(New IO 或 NonBlocking IO)是 Java 1.4 版本开始引入的一种全新的 I/O API,旨在提高 I/O 吞吐量。与传统的阻塞 I/O 相比,NIO 的设计思想更为先进,它采用了 Reactor 模式的事件驱动机制来实现非阻塞 I/...

    nonblocking switch server

    在IT行业中,非阻塞I/O(Non-blocking I/O)是一种网络编程模型,与传统的阻塞I/O相比,它在处理多个连接请求时能更好地利用系统资源,特别是在高并发场景下。非阻塞服务器通常采用事件驱动或者多路复用技术,如...

    nonblocking server

    总结来说,"nonblocking server"是指采用非阻塞I/O模型的服务器,这种模式能够处理大量并发连接,提高系统性能。通过引入MurmurHash3,服务器可以快速处理数据并降低冲突。HTTP状态的打印有助于监控服务器状态,而...

    simple-nodejs-nonblocking-process

    在Node.js环境中,"simple-nodejs-nonblocking-process"这一主题主要关注的是如何利用JavaScript的非阻塞I/O特性来优化程序性能。Node.js是基于Chrome V8引擎的JavaScript运行环境,它的一大特色就是异步、非阻塞I/O...

    Java非阻塞套接字概述

    在传统的Java I/O模型中,阻塞套接字在进行读写操作时,如果数据未准备好,会使得调用线程进入阻塞状态,直到数据准备就绪。这在处理高并发场景时,可能会导致大量线程被创建并阻塞,消耗大量的系统资源。非阻塞套接...

    16-Netty面试题.docx

    Netty 是基于 NIO(Nonblocking IO,非阻塞IO)开发的网络通信框架,对比于 BIO(Blocking I/O,阻塞IO),他的并发性能得到了很大提高。 Netty 的特点 * 高并发:Netty 是一款基于 NIO(Nonblocking IO,非阻塞IO...

    tci6636k2h

    bandwidth for nonblocking access to all processing cores, peripherals, coprocessors, and I/O. This is achieved with four main hardware elements: Multicore Navigator, TeraNet, Multicore Shared Memory ...

Global site tag (gtag.js) - Google Analytics