Java NIO系列教程(一) Java NIO 概述
2017-03-03 11:17
495 查看
Java NIO 由以下几个核心部分组成:
Channels
Buffers
Selectors
虽然Java NIO 中除此之外还有很多类和组件,但在我看来,Channel,Buffer 和 Selector 构成了核心的API。其它组件,如Pipe和FileLock,只不过是与三个核心组件共同使用的工具类。因此,在概述中我将集中在这三个组件上。其它组件会在单独的章节中讲到。
基本上,所有的 IO 在NIO 中都从一个Channel 开始。Channel 有点象流。 数据可以从Channel读到Buffer中,也可以从Buffer 写到Channel中。这里有个图示:
Channel和Buffer有好几种类型。下面是JAVA NIO中的一些主要Channel的实现:
FileChannel
DatagramChannel
SocketChannel
ServerSocketChannel
正如你所看到的,这些通道涵盖了UDP 和 TCP 网络IO,以及文件IO。
与这些类一起的有一些有趣的接口,但为简单起见,我尽量在概述中不提到它们。本教程其它章节与它们相关的地方我会进行解释。
以下是Java NIO里关键的Buffer实现:
ByteBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer
这些Buffer覆盖了你能通过IO发送的基本数据类型:byte, short, int, long, float, double 和 char。
Java NIO 还有个 MappedByteBuffer,用于表示内存映射文件, 我也不打算在概述中说明。
了解Socket看这里:Socket是什么
Socket、SocketChannel二者的实质都是一样的,都是为了实现客户端与服务器端的连接而存在的,但是在使用上,却有很大的区别。具体如下:
所属包不同
Socket在java.net包中,而SocketChannel在java.nio包中。
异步方式不同
从包的不同,我们大体可以推断出他们主要的区别:Socket是阻塞连接(当然我们可以自己实现非阻塞),SocketChannel可以设置非阻塞连接。
使用ServerSocket、Socket类时,服务端Socket往往要为每一个客户端Socket分配一个线程,而每一个线程都有可能处于长时间的阻塞状态中。过多的线程也会影响服务器的性能(可以使用线程池优化,具体看这里:如何编写多线程Socket程序)。而使用SocketChannel、ServerSocketChannel类可以非阻塞通信,这样使得服务器端只需要一个线程就能处理所有客户端socket的请求。
了解阻塞、非阻塞看这里:[阻塞、非阻塞有什么区别][3]
性能不同
一般来说使用SocketChannel会有更好的性能。其实,Socket实际应该比SocketChannel更高效,不过由于使用者设计等原因,效率反而比直接使用SocketChannel低。
使用方式不同
Socket、ServerSocket类可以传入不同参数直接实例化对象并绑定ip和端口,如:
2
而SocketChannel、ServerSocketChannel类需要借助Selector类控制,如:
2
3
4
5
6
下面是SocketChannel方式需要用到的几个核心类:
ServerSocketChannel
ServerSocket的替代类, 支持阻塞通信与非阻塞通信。
SocketChannel
Socket的替代类, 支持阻塞通信与非阻塞通信。
Selector
为ServerSocketChannel监控接收客户端连接就绪事件, 为SocketChannel监控连接服务器读就绪和写就绪事件。
SelectionKey
代表ServerSocketChannel及SocketChannel向Selector注册事件的句柄。当一个
SelectionKey对象位于Selector对象的selected-keys集合中时,就表示与这个SelectionKey对象相关的事件发生了。
在SelectionKey类中有几个静态常量:
SelectionKey.OP_ACCEPT,客户端连接就绪事件,等于监听serversocket.accept(),返回一个socket。
SelectionKey.OP_CONNECT,准备连接服务器就绪,跟上面类似,只不过是对于socket的 相当于监听了socket.connect()。
SelectionKey.OP_READ,读就绪事件, 表示输入流中已经有了可读数据, 可以执行读操作。
SelectionKey.OP_WRITE,写就绪事件, 表示可以执行写操作。
了解如何开发ServerSocketChannel看这里:[如何编写非阻塞SocketChannel程序][4]
Selector允许单线程处理多个 Channel。如果你的应用打开了多个连接(通道),但每个连接的流量都很低,使用Selector就会很方便。例如,在一个聊天服务器中。
这是在一个单线程中使用一个Selector处理3个Channel的图示:
要使用Selector,得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接收等。
原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: Java
NIO系列教程(一) Java NIO 概述
130
About
Latest
Posts
爱生活, 爱编码,更爱玩。
添加本文到我的收藏
Java
NIO系列教程(三) Buffer
Java
NIO系列教程(二) Channel
Java
NIO系列教程(六) Selector
Java
NIO系列教程(七) FileChannel
Java
NIO系列教程(十) Java NIO DatagramChannel
Java
NIO系列教程(八) SocketChannel
Java
NIO系列教程(四) Scatter/Gather
Java
NIO系列教程(十二) Java NIO与IO
Java
NIO系列教程(九) ServerSocketChannel
Java
NIO系列教程(十一) Pipe
Java
NIO系列教程(五) 通道之间的数据传输
Java
NIO 系列教程
Java
IO: Buffered和Data
Java
IO: InputStream
Java
Date Time 教程-java.util.Calendar和GregorianCalendar
Channels
Buffers
Selectors
虽然Java NIO 中除此之外还有很多类和组件,但在我看来,Channel,Buffer 和 Selector 构成了核心的API。其它组件,如Pipe和FileLock,只不过是与三个核心组件共同使用的工具类。因此,在概述中我将集中在这三个组件上。其它组件会在单独的章节中讲到。
Channel 和 Buffer
基本上,所有的 IO 在NIO 中都从一个Channel 开始。Channel 有点象流。 数据可以从Channel读到Buffer中,也可以从Buffer 写到Channel中。这里有个图示:Channel和Buffer有好几种类型。下面是JAVA NIO中的一些主要Channel的实现:
FileChannel
DatagramChannel
SocketChannel
ServerSocketChannel
正如你所看到的,这些通道涵盖了UDP 和 TCP 网络IO,以及文件IO。
与这些类一起的有一些有趣的接口,但为简单起见,我尽量在概述中不提到它们。本教程其它章节与它们相关的地方我会进行解释。
以下是Java NIO里关键的Buffer实现:
ByteBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer
这些Buffer覆盖了你能通过IO发送的基本数据类型:byte, short, int, long, float, double 和 char。
Java NIO 还有个 MappedByteBuffer,用于表示内存映射文件, 我也不打算在概述中说明。
1、Socket、SocketChannel有什么区别
了解Socket看这里:Socket是什么 Socket、SocketChannel二者的实质都是一样的,都是为了实现客户端与服务器端的连接而存在的,但是在使用上,却有很大的区别。具体如下:
所属包不同
Socket在java.net包中,而SocketChannel在java.nio包中。
异步方式不同
从包的不同,我们大体可以推断出他们主要的区别:Socket是阻塞连接(当然我们可以自己实现非阻塞),SocketChannel可以设置非阻塞连接。
使用ServerSocket、Socket类时,服务端Socket往往要为每一个客户端Socket分配一个线程,而每一个线程都有可能处于长时间的阻塞状态中。过多的线程也会影响服务器的性能(可以使用线程池优化,具体看这里:如何编写多线程Socket程序)。而使用SocketChannel、ServerSocketChannel类可以非阻塞通信,这样使得服务器端只需要一个线程就能处理所有客户端socket的请求。
了解阻塞、非阻塞看这里:[阻塞、非阻塞有什么区别][3]
性能不同
一般来说使用SocketChannel会有更好的性能。其实,Socket实际应该比SocketChannel更高效,不过由于使用者设计等原因,效率反而比直接使用SocketChannel低。
使用方式不同
Socket、ServerSocket类可以传入不同参数直接实例化对象并绑定ip和端口,如:
Socket socket = new Socket("127.0.0.1", "8000"); ServerSocket serverSocket = new ServerSocket("8000");1
2
而SocketChannel、ServerSocketChannel类需要借助Selector类控制,如:
Selector selector = Selector.open(); ServerSocketChannel serverChannel = ServerSocketChannel.open(); serverChannel.configureBlocking(false); // 设置为非阻塞方式,如果为true 那么就为传统的阻塞方式 serverChannel.socket().bind(new InetSocketAddress(port)); // 绑定IP 及 端口 serverChannel.register(selector, SelectionKey.OP_ACCEPT); // 注册 OP_ACCEPT事件 new ServerThread().start(); // 开启一个线程 处理所有请求1
2
3
4
5
6
2、SocketChannel方式有什么核心类
下面是SocketChannel方式需要用到的几个核心类:ServerSocketChannel
ServerSocket的替代类, 支持阻塞通信与非阻塞通信。
SocketChannel
Socket的替代类, 支持阻塞通信与非阻塞通信。
Selector
为ServerSocketChannel监控接收客户端连接就绪事件, 为SocketChannel监控连接服务器读就绪和写就绪事件。
SelectionKey
代表ServerSocketChannel及SocketChannel向Selector注册事件的句柄。当一个
SelectionKey对象位于Selector对象的selected-keys集合中时,就表示与这个SelectionKey对象相关的事件发生了。
在SelectionKey类中有几个静态常量:
SelectionKey.OP_ACCEPT,客户端连接就绪事件,等于监听serversocket.accept(),返回一个socket。
SelectionKey.OP_CONNECT,准备连接服务器就绪,跟上面类似,只不过是对于socket的 相当于监听了socket.connect()。
SelectionKey.OP_READ,读就绪事件, 表示输入流中已经有了可读数据, 可以执行读操作。
SelectionKey.OP_WRITE,写就绪事件, 表示可以执行写操作。
了解如何开发ServerSocketChannel看这里:[如何编写非阻塞SocketChannel程序][4]
Selector
Selector允许单线程处理多个 Channel。如果你的应用打开了多个连接(通道),但每个连接的流量都很低,使用Selector就会很方便。例如,在一个聊天服务器中。这是在一个单线程中使用一个Selector处理3个Channel的图示:
要使用Selector,得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接收等。
原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: Java
NIO系列教程(一) Java NIO 概述
130
About
Latest
Posts
Airu
爱生活, 爱编码,更爱玩。添加本文到我的收藏
Related Posts:
JavaNIO系列教程(三) Buffer
Java
NIO系列教程(二) Channel
Java
NIO系列教程(六) Selector
Java
NIO系列教程(七) FileChannel
Java
NIO系列教程(十) Java NIO DatagramChannel
Java
NIO系列教程(八) SocketChannel
Java
NIO系列教程(四) Scatter/Gather
Java
NIO系列教程(十二) Java NIO与IO
Java
NIO系列教程(九) ServerSocketChannel
Java
NIO系列教程(十一) Pipe
Java
NIO系列教程(五) 通道之间的数据传输
Java
NIO 系列教程
Java
IO: Buffered和Data
Java
IO: InputStream
Java
Date Time 教程-java.util.Calendar和GregorianCalendar
相关文章推荐
- Java NIO系列教程(一) Java NIO 概述
- Java NIO系列教程(一) Java NIO 概述
- Java NIO系列教程(一) Java NIO 概述
- Java NIO系列教程(一) Java NIO 概述
- Java NIO系列教程(一) Java NIO 概述
- Java NIO系列教程(一) Java NIO 概述
- Java NIO系列教程(一) Java NIO 概述
- Java NIO系列教程(一) Java NIO 概述
- Java NIO系列教程(一) Java NIO 概述
- Java NIO系列教程(一) Java NIO 概述
- Java NIO系列教程(一) Java NIO 概述
- Java NIO系列教程(一) Java NIO 概述
- Java NIO系列教程(一) Java NIO 概述
- Java NIO系列教程(一) Java NIO 概述
- Java NIO系列教程(一) Java NIO 概述
- Java NIO系列教程(一) Java NIO 概述
- 1.Java NIO系列教程之概述
- Java NIO系列教程(一) Java NIO 概述
- Java NIO系列教程(一) Java NIO 概述
- Java NIO系列教程(一) Java NIO 概述