朋友发nio朋友是什么意思思

java nio在什么时候会触发write事件了,想了很久都想不明白的事情
比如我写了个服务端程序,流程为:接受客户端连接,读取客户端发过来的数据,处理数据,处理完成后再写入数据。
我在读取事件里面读取了数据处理完后,怎么去触发写事件,难道是直接在读取事件里面就直接把数据写出去?那这样的话,要读事件有什么用?
读事件触发以后,你接受到服务器的信息,进行一些业务逻辑处理,处理完成之后假如你要向服务器返回信息时把事件改为写:channel.register(selector, SelectionKey.OP_WRITE),一般处理完逻辑之后改为register(selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ) ,这样在等待消息的那段时间即可进行读操作又可进行写操作!
引用来自“qyj”的答案读事件触发以后,你接受到服务器的信息,进行一些业务逻辑处理,处理完成之后假如你要向服务器返回信息时把事件改为写:channel.register(selector, SelectionKey.OP_WRITE),一般处理完逻辑之后改为register(selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ) ,这样在等待消息的那段时间即可进行读操作又可进行写操作!意思是我先只注册写事件register(selector, SelectionKey.OP_READ),读取到数据,处理完业务逻辑,然后再注册写事件?那这样就会触发写事件吗?
我现在也正在纠结这个问题,读取客户端消息在读事件里面执行,如果需要回复客户端也只需要socketChannel.write(byteBuffer);写事件有什么特殊的用处么?
引用来自“时间在追我”的评论
我现在也正在纠结这个问题,读取客户端消息在读事件里面执行,如果需要回复客户端也只需要socketChannel.write(byteBuffer);写事件有什么特殊的用处么?
我也在纠结,写的话,我想写就可以写啊,还用得着事件吗?写事件是否是用来通知客户端,服务端已经准备好读了。写不是用在自己身上,而是用到对方身上的吧
http://blog.csdn.net/zhouhl_cn/article/details/6582435Java 高并发八:NIO和AIO详解
作者:Hosee
字体:[ ] 类型:转载 时间:
本文主要介绍Java 高并发NIO和AIO 的知识,这里整理了详细的资料,并详细介绍了 1. 什么是NIO 2. Buffer 3. Channel 4. 网络编程 5. AIO的知识,有需要的小伙伴可以参考下
IO感觉上和多线程并没有多大关系,但是NIO改变了线程在应用层面使用的方式,也解决了一些实际的困难。而AIO是异步IO和前面的系列也有点关系。在此,为了学习和记录,也写一篇文章来介绍NIO和AIO。
1. 什么是NIO
NIO是New I/O的简称,与旧式的基于流的I/O方法相对,从名字看,它表示新的一套Java I/O标 准。它是在Java 1.4中被纳入到JDK中的,并具有以下特性:
NIO是基于块(Block)的,它以块为基本单位处理数据 (硬盘上存储的单位也是按Block来存储,这样性能上比基于流的方式要好一些)
为所有的原始类型提供(Buffer)缓存支持
增加通道(Channel)对象,作为新的原始 I/O 抽象
支持锁(我们在平时使用时经常能看到会出现一些.lock的文件,这说明有线程正在使用这把锁,当线程释放锁时,会把这个文件删除掉,这样其他线程才能继续拿到这把锁)和内存映射文件的文件访问接口
提供了基于Selector的异步网络I/O
所有的从通道中的读写操作,都要经过Buffer,而通道就是io的抽象,通道的另一端就是操纵的文件。
Java中Buffer的实现。基本的数据类型都有它对应的Buffer
Buffer的简单使用例子:
import java.io.F
import java.io.FileInputS
import java.nio.ByteB
import java.nio.channels.FileC
public class Test {
public static void main(String[] args) throws Exception {
FileInputStream fin = new FileInputStream(new File(
"d:\\temp_buffer.tmp"));
FileChannel fc = fin.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
fc.read(byteBuffer);
fc.close();
byteBuffer.flip();//读写转换
总结下使用的步骤是:
1. 得到Channel
2. 申请Buffer
3. 建立Channel和Buffer的读/写关系
下面的例子是使用NIO来复制文件:
public static void nioCopyFile(String resource, String destination)
throws IOException {
FileInputStream fis = new FileInputStream(resource);
FileOutputStream fos = new FileOutputStream(destination);
FileChannel readChannel = fis.getChannel(); // 读文件通道
FileChannel writeChannel = fos.getChannel(); // 写文件通道
ByteBuffer buffer = ByteBuffer.allocate(1024); // 读入数据缓存
while (true) {
buffer.clear();
int len = readChannel.read(buffer); // 读入数据
if (len == -1) {
// 读取完毕
buffer.flip();
writeChannel.write(buffer); // 写入文件
readChannel.close();
writeChannel.close();
Buffer中有3个重要的参数:位置(position)、容量(capactiy)和上限(limit)
这里要区别下容量和上限,比如一个Buffer有10KB,那么10KB就是容量,我将5KB的文件读到Buffer中,那么上限就是5KB。
下面举个例子来理解下这3个重要的参数:
public static void main(String[] args) throws Exception {
ByteBuffer b = ByteBuffer.allocate(15); // 15个字节大小的缓冲区
System.out.println("limit=" + b.limit() + " capacity=" + b.capacity()
+ " position=" + b.position());
for (int i = 0; i & 10; i++) {
// 存入10个字节数据
b.put((byte) i);
System.out.println("limit=" + b.limit() + " capacity=" + b.capacity()
+ " position=" + b.position());
b.flip(); // 重置position
System.out.println("limit=" + b.limit() + " capacity=" + b.capacity()
+ " position=" + b.position());
for (int i = 0; i & 5; i++) {
System.out.print(b.get());
System.out.println();
System.out.println("limit=" + b.limit() + " capacity=" + b.capacity()
+ " position=" + b.position());
System.out.println("limit=" + b.limit() + " capacity=" + b.capacity()
+ " position=" + b.position());
整个过程如图:
此时position从0到10,capactiy和limit不变。
该操作会重置position,通常,将buffer从写模式转换为读 模式时需要执行此方法 flip()操作不仅重置了当前的position为0,还将limit设置到当前position的位置 。
limit的意义在于,来确定哪些数据是有意义的,换句话说,从position到limit之间的数据才是有意义的数据,因为是上次操作的数据。所以flip操作往往是读写转换的意思。
意义同上。
而Buffer中大多数的方法都是去改变这3个参数来达到某些功能的:
public final Buffer rewind()
将position置零,并清除标志位(mark)
public final Buffer clear()
将position置零,同时将limit设置为capacity的大小,并清除了标志mark
public final Buffer flip()
先将limit设置到position所在位置,然后将position置零,并清除标志位mark,通常在读写转换时使用
文件映射到内存
public static void main(String[] args) throws Exception {
RandomAccessFile raf = new RandomAccessFile("C:\\mapfile.txt", "rw");
FileChannel fc = raf.getChannel();
// 将文件映射到内存中
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0,
raf.length());
while (mbb.hasRemaining()) {
System.out.print((char) mbb.get());
mbb.put(0, (byte) 98); // 修改文件
raf.close();
对MappedByteBuffer的修改就相当于修改文件本身,这样操作的速度是很快的。
3. Channel
多线程网络服务器的一般结构:
简单的多线程服务器:
public static void main(String[] args) throws Exception {
ServerSocket echoServer =
Socket clientSocket =
echoServer = new ServerSocket(8000);
} catch (IOException e) {
System.out.println(e);
while (true) {
clientSocket = echoServer.accept();
System.out.println(clientSocket.getRemoteSocketAddress()
+ " connect!");
tp.execute(new HandleMsg(clientSocket));
} catch (IOException e) {
System.out.println(e);
功能就是服务器端读到什么数据,就向客户端回写什么数据。
这里的tp是一个线程池,HandleMsg是处理消息的类。
static class HandleMsg implements Runnable{
省略部分信息
public void run(){
is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
os = new PrintWriter(clientSocket.getOutputStream(), true);
// 从InputStream当中读取客户端所发送的数据
String inputLine =
long b=System. currentTimeMillis ();
while ((inputLine = is.readLine()) != null)
os.println(inputLine);
long e=System. currentTimeMillis ();
System. out.println ("spend:"+(e - b)+" ms ");
} catch (IOException e) {
e.printStackTrace();
public static void main(String[] args) throws Exception {
Socket client =
PrintWriter writer =
BufferedReader reader =
client = new Socket();
client.connect(new InetSocketAddress("localhost", 8000));
writer = new PrintWriter(client.getOutputStream(), true);
writer.println("Hello!");
writer.flush();
reader = new BufferedReader(new InputStreamReader(
client.getInputStream()));
System.out.println("from server: " + reader.readLine());
} catch (Exception e) {
} finally {
// 省略资源关闭
以上的网络编程是很基本的,使用这种方式,会有一些问题:
为每一个客户端使用一个线程,如果客户端出现延时等异常,线程可能会被占用很长时间。因为数据的准备和读取都在这个线程中。此时,如果客户端数量众多,可能会消耗大量的系统资源。
使用非阻塞的NIO (读取数据不等待,数据准备好了再工作)
为了体现NIO使用的高效。
这里先模拟一个低效的客户端来模拟因网络而延时的情况:
private static ExecutorService tp= Executors.newCachedThreadPool();
private static final int sleep_time=00;
public static class EchoClient implements Runnable{
public void run(){
client = new Socket();
client.connect(new InetSocketAddress("localhost", 8000));
writer = new PrintWriter(client.getOutputStream(), true);
writer.print("H");
LockSupport.parkNanos(sleep_time);
writer.print("e");
LockSupport.parkNanos(sleep_time);
writer.print("l");
LockSupport.parkNanos(sleep_time);
writer.print("l");
LockSupport.parkNanos(sleep_time);
writer.print("o");
LockSupport.parkNanos(sleep_time);
writer.print("!");
LockSupport.parkNanos(sleep_time);
writer.println();
writer.flush();
}catch(Exception e)
服务器端输出:
spend:6000ms
spend:6000ms
spend:6000ms
spend:6001ms
spend:6002ms
spend:6002ms
spend:6002ms
spend:6002ms
spend:6003ms
spend:6003ms
while ((inputLine = is.readLine()) != null)
是阻塞的,所以时间都花在等待中。
如果用NIO来处理这个问题会怎么做呢?
NIO有一个很大的特点就是:把数据准备好了再通知我
而Channel有点类似于流,一个Channel可以和文件或者网络Socket对应 。
selector是一个选择器,它可以选择某一个Channel,然后做些事情。
一个线程可以对应一个selector,而一个selector可以轮询多个Channel,而每个Channel对应了一个Socket。
与上面一个线程对应一个Socket相比,使用NIO后,一个线程可以轮询多个Socket。
当selector调用select()时,会查看是否有客户端准备好了数据。当没有数据被准备好时,select()会阻塞。平时都说NIO是非阻塞的,但是如果没有数据被准备好还是会有阻塞现象。
当有数据被准备好时,调用完select()后,会返回一个SelectionKey,SelectionKey表示在某个selector上的某个Channel的数据已经被准备好了。
只有在数据准备好时,这个Channel才会被选择。
这样NIO实现了一个线程来监控多个客户端。
而刚刚模拟的网络延迟的客户端将不会影响NIO下的线程,因为某个Socket网络延迟时,数据还未被准备好,selector是不会选择它的,而会选择其他准备好的客户端。
selectNow()与select()的区别在于,selectNow()是不阻塞的,当没有客户端准备好数据时,selectNow()不会阻塞,将返回0,有客户端准备好数据时,selectNow()返回准备好的客户端的个数。
主要代码:
import java.net.InetA
import java.net.InetSocketA
import java.net.S
import java.nio.ByteB
import java.nio.channels.SelectionK
import java.nio.channels.S
import java.nio.channels.ServerSocketC
import java.nio.channels.SocketC
import java.nio.channels.spi.AbstractS
import java.nio.channels.spi.SelectorP
import java.util.HashM
import java.util.I
import java.util.LinkedL
import java.util.M
import java.util.S
import java.util.concurrent.ExecutorS
import java.util.concurrent.E
public class MultiThreadNIOEchoServer {
public static Map&Socket, Long& geym_time_stat = new HashMap&Socket, Long&();
class EchoClient {
private LinkedList&ByteBuffer&
EchoClient() {
outq = new LinkedList&ByteBuffer&();
public LinkedList&ByteBuffer& getOutputQueue() {
public void enqueue(ByteBuffer bb) {
outq.addFirst(bb);
class HandleMsg implements Runnable {
SelectionK
public HandleMsg(SelectionKey sk, ByteBuffer bb) {
public void run() {
// TODO Auto-generated method stub
EchoClient echoClient = (EchoClient) sk.attachment();
echoClient.enqueue(bb);
sk.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);
selector.wakeup();
private ExecutorService tp = Executors.newCachedThreadPool();
private void startServer() throws Exception {
selector = SelectorProvider.provider().openSelector();
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
InetSocketAddress isa = new InetSocketAddress(8000);
ssc.socket().bind(isa);
// 注册感兴趣的事件,此处对accpet事件感兴趣
SelectionKey acceptKey = ssc.register(selector, SelectionKey.OP_ACCEPT);
for (;;) {
selector.select();
Set readyKeys = selector.selectedKeys();
Iterator i = readyKeys.iterator();
long e = 0;
while (i.hasNext()) {
SelectionKey sk = (SelectionKey) i.next();
i.remove();
if (sk.isAcceptable()) {
doAccept(sk);
} else if (sk.isValid() && sk.isReadable()) {
if (!geym_time_stat.containsKey(((SocketChannel) sk
.channel()).socket())) {
geym_time_stat.put(
((SocketChannel) sk.channel()).socket(),
System.currentTimeMillis());
doRead(sk);
} else if (sk.isValid() && sk.isWritable()) {
doWrite(sk);
e = System.currentTimeMillis();
long b = geym_time_stat.remove(((SocketChannel) sk
.channel()).socket());
System.out.println("spend:" + (e - b) + "ms");
private void doWrite(SelectionKey sk) {
// TODO Auto-generated method stub
SocketChannel channel = (SocketChannel) sk.channel();
EchoClient echoClient = (EchoClient) sk.attachment();
LinkedList&ByteBuffer& outq = echoClient.getOutputQueue();
ByteBuffer bb = outq.getLast();
int len = channel.write(bb);
if (len == -1) {
disconnect(sk);
if (bb.remaining() == 0) {
outq.removeLast();
} catch (Exception e) {
// TODO: handle exception
disconnect(sk);
if (outq.size() == 0) {
sk.interestOps(SelectionKey.OP_READ);
private void doRead(SelectionKey sk) {
// TODO Auto-generated method stub
SocketChannel channel = (SocketChannel) sk.channel();
ByteBuffer bb = ByteBuffer.allocate(8192);
len = channel.read(bb);
if (len & 0) {
disconnect(sk);
} catch (Exception e) {
// TODO: handle exception
disconnect(sk);
bb.flip();
tp.execute(new HandleMsg(sk, bb));
private void disconnect(SelectionKey sk) {
// TODO Auto-generated method stub
//省略略干关闭操作
private void doAccept(SelectionKey sk) {
// TODO Auto-generated method stub
ServerSocketChannel server = (ServerSocketChannel) sk.channel();
SocketChannel clientC
clientChannel = server.accept();
clientChannel.configureBlocking(false);
SelectionKey clientKey = clientChannel.register(selector,
SelectionKey.OP_READ);
EchoClient echoClinet = new EchoClient();
clientKey.attach(echoClinet);
InetAddress clientAddress = clientChannel.socket().getInetAddress();
System.out.println("Accepted connection from "
+ clientAddress.getHostAddress());
} catch (Exception e) {
// TODO: handle exception
public static void main(String[] args) {
// TODO Auto-generated method stub
MultiThreadNIOEchoServer echoServer = new MultiThreadNIOEchoServer();
echoServer.startServer();
} catch (Exception e) {
// TODO: handle exception
代码仅作参考,主要的特点是,对不同事件的感兴趣来做不同的事。
当用之前模拟的那个延迟的客户端时,这次的时间消耗就在2ms到11ms之间了。性能提升是很明显的。
1. NIO会将数据准备好后,再交由应用进行处理,数据的读取/写入过程依然在应用线程中完成,只是将等待的时间剥离到单独的线程中去。
2. 节省数据准备时间(因为Selector可以复用)
AIO的特点:
1. 读完了再通知我
2. 不会加快IO,只是在读完后进行通知
3. 使用回调函数,进行业务处理
AIO的相关代码:
AsynchronousServerSocketChannel
server = AsynchronousServerSocketChannel.open().bind( new InetSocketAddress (PORT));
使用server上的accept方法
public abstract &A& void accept(A attachment,CompletionHandler&AsynchronousSocketChannel,? super A& handler);
CompletionHandler为回调接口,当有客户端accept之后,就做handler中的事情。
示例代码:
server.accept(null,
new CompletionHandler&AsynchronousSocketChannel, Object&() {
final ByteBuffer buffer = ByteBuffer.allocate(1024);
public void completed(AsynchronousSocketChannel result,
Object attachment) {
System.out.println(Thread.currentThread().getName());
Future&Integer& writeResult =
buffer.clear();
result.read(buffer).get(100, TimeUnit.SECONDS);
buffer.flip();
writeResult = result.write(buffer);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
} finally {
server.accept(null, this);
writeResult.get();
result.close();
} catch (Exception e) {
System.out.println(e.toString());
public void failed(Throwable exc, Object attachment) {
System.out.println("failed: " + exc);
这里使用了Future来实现即时返回,关于Future请参考上一篇
在理解了NIO的基础上,看AIO,区别在于AIO是等读写过程完成后再去调用回调函数。
NIO是同步非阻塞的
AIO是异步非阻塞的
由于NIO的读写过程依然在应用线程里完成,所以对于那些读写过程时间长的,NIO就不太适合。
而AIO的读写过程完成后才被通知,所以AIO能够胜任那些重量级,读写过程长的任务。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具让天下没有难学的技术
感谢支付宝同事[]在本站发布此文。
这博文的系列主要是为了更好的了解一个完整的nio框架的编程细节以及演进过程,我选了同父(Trustin Lee)的两个框架netty与mina做对比。版本涉及了netty3.x、netty4.x、mina1.x、mina2.x、mina3.x。这里并没有写netty5.x的细节,看了,似乎有一些比较有意思的改动,准备单独写一篇netty4.x与netty5.x的不同。
(12 votes, average: 4.25 out of 5)
Loading...
作者:Jakob Jenkov 译者:浪迹v 校对:丁一
Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件。这样,一个单独的线程可以管理多个channel,从而管理多个网络连接。
下面是本文所涉及到的主题列表:
(45 votes, average: 4.40 out of 5)
Loading...
作者:Jakob Jenkov
译者:郑玉婷
校对:丁一
Java NIO中的DatagramChannel是一个能收发UDP包的通道。因为UDP是无连接的网络协议,所以不能像其它通道那样读取和写入。它发送和接收的是数据包。
(22 votes, average: 4.59 out of 5)
Loading...
作者:Jakob Jenkov
译者:airu
校对:丁一
Java NIO 由以下几个核心部分组成:
虽然Java NIO 中除此之外还有很多类和组件,但在我看来,Channel,Buffer 和 Selector 构成了核心的API。其它组件,如Pipe和FileLock,只不过是与三个核心组件共同使用的工具类。因此,在概述中我将集中在这三个组件上。其它组件会在单独的章节中讲到。
(91 votes, average: 4.53 out of 5)
Loading...
作者:Jakob Jenkov
译者:周泰
校对:丁一
Java NIO中的FileChannel是一个连接到文件的通道。可以通过文件通道读写文件。
FileChannel无法设置为非阻塞模式,它总是运行在阻塞模式下。
(34 votes, average: 4.38 out of 5)
Loading...
作者:Jakob Jenkov
译者:airu
校对:丁一
Java NIO的通道类似流,但又有些不同:
既可以从通道中读取数据,又可以写数据到通道。但流的读写通常是单向的。
通道可以异步地读写。
通道中的数据总是要先读到一个Buffer,或者总是要从一个Buffer中写入。
正如上面所说,从通道读取数据到缓冲区,从缓冲区写入数据到通道。如下图所示:
(51 votes, average: 4.61 out of 5)
Loading...
作者:Jakob Jenkov
译者:airu
校对:丁一
Java NIO中的Buffer用于和NIO通道进行交互。如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的。
缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存。
下面是NIO Buffer相关的话题列表:
(40 votes, average: 4.48 out of 5)
Loading...
作者:Jakob Jenkov
译者:郑玉婷
校对:丁一
Java NIO中的SocketChannel是一个连接到TCP网络套接字的通道。可以通过以下2种方式创建SocketChannel:
打开一个SocketChannel并连接到互联网上的某台服务器。
一个新连接到达ServerSocketChannel时,会创建一个SocketChannel。
(34 votes, average: 4.65 out of 5)
Loading...
作者:Jakob Jenkov
译者:黄忠
校对:丁一
Java NIO 管道是2个线程之间的单向数据连接。Pipe有一个source通道和一个sink通道。数据会被写到sink通道,从source通道读取。
这里是Pipe原理的图示:
(21 votes, average: 4.00 out of 5)
Loading...
作者:Jakob Jenkov
译者:郑玉婷
校对:丁一
Java NIO中的 ServerSocketChannel 是一个可以监听新进来的TCP连接的通道, 就像标准IO中的ServerSocket一样。ServerSocketChannel类在 java.nio.channels包中。
(22 votes, average: 4.82 out of 5)
Loading...
原文地址:
作者:Jakob Jenkov
译者:郭蕾
校对:周泰
在Java NIO中,如果两个通道中有一个是FileChannel,那你可以直接将数据从一个channel(译者注:channel中文常译作通道)传输到另外一个channel。
transferFrom()
FileChannel的transferFrom()方法可以将数据从源通道传输到FileChannel中(译者注:这个方法在JDK文档中的解释为将字节从给定的可读取字节通道传输到此通道的文件中)。下面是一个简单的例子:
RandomAccessFile fromFile = new RandomAccessFile(&fromFile.txt&, &rw&);
FileChannel
fromChannel = fromFile.getChannel();
RandomAccessFile toFile = new RandomAccessFile(&toFile.txt&, &rw&);
FileChannel
toChannel = toFile.getChannel();
long position = 0;
long count = fromChannel.size();
toChannel.transferFrom(position, count, fromChannel);
方法的输入参数position表示从position处开始向目标文件写入数据,count表示最多传输的字节数。如果源通道的剩余空间小于 count 个字节,则所传输的字节数要小于请求的字节数。
此外要注意,在SoketChannel的实现中,SocketChannel只会传输此刻准备好的数据(可能不足count字节)。因此,SocketChannel可能不会将请求的所有数据(count个字节)全部传输到FileChannel中。
transferTo()
transferTo()方法将数据从FileChannel传输到其他的channel中。下面是一个简单的例子:
RandomAccessFile fromFile = new RandomAccessFile(&fromFile.txt&, &rw&);
FileChannel
fromChannel = fromFile.getChannel();
RandomAccessFile toFile = new RandomAccessFile(&toFile.txt&, &rw&);
FileChannel
toChannel = toFile.getChannel();
long position = 0;
long count = fromChannel.size();
fromChannel.transferTo(position, count, toChannel);
是不是发现这个例子和前面那个例子特别相似?除了调用方法的FileChannel对象不一样外,其他的都一样。
上面所说的关于SocketChannel的问题在transferTo()方法中同样存在。SocketChannel会一直传输数据直到目标buffer被填满。
(29 votes, average: 4.69 out of 5)
Loading...
原文地址:
作者:Jakob Jenkov
译者:郭蕾
Java NIO开始支持scatter/gather,scatter/gather用于描述从Channel(译者注:Channel在中文经常翻译为通道)中读取或者写入到Channel的操作。
分散(scatter)从Channel中读取是指在读操作时将读取的数据写入多个buffer中。因此,Channel将从Channel中读取的数据“分散(scatter)”到多个Buffer中。
聚集(gather)写入Channel是指在写操作时将多个buffer的数据写入同一个Channel,因此,Channel 将多个Buffer中的数据“聚集(gather)”后发送到Channel。
scatter / gather经常用于需要将传输的数据分开处理的场合,例如传输一个由消息头和消息体组成的消息,你可能会将消息体和消息头分散到不同的buffer中,这样你可以方便的处理消息头和消息体。
(49 votes, average: 4.71 out of 5)
Loading...
作者:Jakob Jenkov
译者:郭蕾
校对:方腾飞
Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式。
Java NIO: Channels and Buffers(通道和缓冲区)
标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。
Java NIO: Non-blocking IO(非阻塞IO)
Java NIO可以让你非阻塞的使用IO,例如:当线程从通道读取数据到缓冲区时,线程还是可以进行其他事情。当数据被写入到缓冲区时,线程可以继续处理它。从缓冲区写入通道也类似。
Java NIO: Selectors(选择器)
Java NIO引入了选择器的概念,选择器用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的线程可以监听多个数据通道。
下面是Java NIO系列文章的目录:
(待翻译)
(待翻译)
(待翻译)
(43 votes, average: 4.56 out of 5)
Loading...
原文地址:
作者:Jakob Jenkov
译者:郭蕾
校对:方腾飞
当学习了Java NIO和IO的API后,一个问题马上涌入脑海:
我应该何时使用IO,何时使用NIO呢?在本文中,我会尽量清晰地解析Java NIO和IO的差异、它们的使用场景,以及它们如何影响您的代码设计。
Java NIO和IO的主要区别
下表总结了Java NIO和IO之间的主要差别,我会更详细地描述表中每部分的差异。
(29 votes, average: 4.52 out of 5)
Loading...}

我要回帖

更多关于 nio是什么意思 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信