欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

NIO概述,

来源: javaer 分享于  点击 26637 次 点评:117

NIO概述,


一.Java NIO Tutorial

Java NIO (New IO) is an alternative(替代的,可供选择的) IO API for Java (from Java 1.4), meaning alternative to the standardJava IO and Java Networking API's. Java NIO offers a different way of working with IO than the standard IO API's.

Java NIO: Channels and Buffers

In the standard IO API you work with byte streams and character streams. In NIO you work with channels and buffers. Data is always read from a channel into a buffer, or written from a buffer to a channel.(数据总是从channel读取到buffer或者从buffer写到通道)

Java NIO: Non-blocking IO

Java NIO enables you to do non-blocking IO(非阻塞IO). For instance, a thread can ask a channel to read data into a buffer. While the channel reads data into the buffer, the thread can do something else. Once data is read into the buffer, the thread can then continue processing it. The same is true for writing data to channels.

Java NIO: Selectors

Java NIO contains the concept of "selectors". A selector is an object that can monitor multiple channels for events (like: connection opened, data arrived etc.). Thus, a single thread can monitor multiple channels for data.

在java.nio.channels.SelectionKey中设定了四个events:

public static final int OP_READ = 1 << 0;
public static final int OP_WRITE = 1 << 2;
public static final int OP_CONNECT = 1 << 3;
public static final int OP_ACCEPT = 1 << 4;

二.Java NIO Overview

Java NIO consist of the following core components:

  • Channels
  • Buffers
  • Selectors

Java NIO has more classes and components than these, but the ChannelBuffer and Selector forms the core of the API, in my opinion. The rest of the components, like Pipe and FileLock are merely utility(有多种用途的) classes to be used in conjunction(连接) with the three core components. Therefore, I'll focus on these three components in this NIO overview. The other components are explained in their own texts elsewhere in this tutorial. See the menu at the top corner of this page.

Channels and Buffers

Typically, all IO in NIO starts with a Channel. Channel is a bit like a stream. From the Channel data can be read into a Buffer. Data can also be written from a Buffer into a Channel. Here is an illustration(插图,说明) of that:

There are several Channel and Buffer types. Here is a list of the primary Channel implementations in Java NIO(四大通道):

  • FileChannel
  • DatagramChannel
  • SocketChannel
  • ServerSocketChannel

As you can see, these channels cover(包括了,覆盖了) UDP + TCP network IO, and file IO.

There are a few interesting interfaces accompanying(伴随着) these classes too, but I'll keep them out of this Java NIO overview for simplicity's sake(缘故;理由). They'll be explained where relevant, in other texts of this Java NIO tutorial.

Here is a list of the core Buffer implementations in Java NIO(只要记住八大基本类型少一个boolean):

  • ByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

These Buffer's cover the basic data types that you can send via IO: byte, short, int, long, float, double and characters.

Java NIO also has a MappedByteBuffer which is used in conjunction with memory mapped files. I'll leave this Buffer out of this overview though.

Selectors

Selector allows a single thread to handle multiple Channel's. This is handy(方便的) if your application has many connections (Channels) open, but only has low traffic(流量,交通) on each connection. For instance, in a chat server.

Here is an illustration of a thread using a Selector to handle 3 Channel's:

To use a Selector you register the Channel's with it(通道需要注册到Selector中). Then you call it's select() method. This method will block until there is an event ready for one of the registered channels. Once the method returns, the thread can then process these events.  Examples of events are incoming connection, data received etc.

注册和调用select()的代码如下:

serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);//注册
selector.select(); //会阻塞

下面我举一个用NIO写的简单服务器来进行具体的说明,代码如下,可自己运行:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

/**
 * Created by wbx on 2018/12/27.
 */
public class NIOServer extends Thread {

    public static final int PORT= 8888;

    public void run() {
        try (Selector selector = Selector.open();
             ServerSocketChannel serverSocket = ServerSocketChannel.open();) {// 创建 Selector 和 Channel

            serverSocket.bind(new InetSocketAddress(InetAddress.getLocalHost(), PORT));
            serverSocket.configureBlocking(false);//明确配置为非阻塞模式,不然阻塞模式下是不能注册到Selector的,会抛IllegalBlockingModeException

            // 注册到 Selector,并说明关注点
            serverSocket.register(selector, SelectionKey.OP_ACCEPT);//向selector注册ServerSocketChannel,并指明关注点为新的连接请求
            while (true) {
                selector.select();// 阻塞,等待就绪的 Channel,这是关键点之一,当有channel接入时会被唤醒
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                Iterator<SelectionKey> iter = selectedKeys.iterator();
                while (iter.hasNext()) {
                    SelectionKey key = iter.next();

                    // 生产系统中一般会额外进行就绪状态检查
                    sayHelloWorld((ServerSocketChannel) key.channel());

                    iter.remove();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void sayHelloWorld(ServerSocketChannel server) throws IOException {
        try (SocketChannel client = server.accept();) {
            //向客户端写一条消息
            client.write(Charset.defaultCharset().encode("Hello world!"));
        }
    }
    public static void main(String[] args) throws IOException {
        NIOServer server = new NIOServer();
        server.start();
        try (Socket client = new Socket(InetAddress.getLocalHost(), PORT)) {
            //读取服务端的消息
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(client.getInputStream()));
            bufferedReader.lines().forEach(s -> System.out.println(s));
        }
    }
}

输出结果:

Hello world!

 

 

 

引用:

http://tutorials.jenkov.com/java-nio/overview.html

相关文章

    暂无相关文章
相关栏目:

用户点评