简体   繁体   English

如何在JAVA非阻塞I / O(NIO)API中使用多个内核?

[英]How to use multiple cores in the JAVA Non Blocking I/O (NIO) API?

JAVA NIO provides an API to write a TCP server using NIO architecture, as follows. JAVA NIO提供了使用NIO架构编写TCP服务器的API,如下所示。

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.Buffer;
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.text.ParseException;
import java.util.*;

public class NIOServer implements Runnable{
    private InetAddress addr;
    private int port;
    private Selector selector;

    public NIOServer(InetAddress addr, int port) throws IOException {
        this.addr = addr;
        this.port = port;
    }

    public void run(){
        try {
            startServer();
        }catch(IOException ex){
            System.out.println(ex.getMessage());
        }
    }

    private void startServer() throws IOException {

        this.selector = Selector.open();
        ServerSocketChannel serverChannel = serverSocketChannel.open();
        serverChannel.configureBlocking(false);
        InetSocketAddress listenAddr = new InetSocketAddress(this.addr, this.port);
        serverChannel.socket().bind(listenAddr);
        serverChannel.register(this.selector, SelectionKey.OP_ACCEPT);


        while (true) {

            this.selector.select();


            Iterator keys = this.selector.selectedKeys().iterator();
            while (keys.hasNext()) {
                SelectionKey key = (SelectionKey) keys.next();


                keys.remove();

                if (! key.isValid()) {
                    continue;
                }

                if (key.isAcceptable()) {
                    this.accept(key);
                }
                else if (key.isReadable()) {
                    this.read(key);
                }
                else if (key.isWritable()) {
                    this.write(key);
                }
            }
        }
    }
}

This uses a single thread that will process events such as read, write and accept. 这使用单个线程来处理诸如读取,写入和接受之类的事件。

Compared to Blocking thread per connection architecture this is much preferred because of its non-blocking nature that causes minimum cache misses, thread overheads, low cpu migrations. 与阻塞每个连接的线程体系结构相比,这是更可取的,因为它具有非阻塞特性,可最大程度地减少缓存丢失,线程开销和较低的cpu迁移。

However, this architecture uses only a single thread. 但是,此体系结构仅使用一个线程。 In a multi-process environment (for example 4 core cpu), NIO architecture wastes other cores. 在多进程环境(例如4核cpu)中,NIO架构浪费了其他核。 Is there a design approach I can use to utilize all the cores with NIO architecture? 我是否可以使用一种设计方法来利用NIO架构的所有内核?

NIO2 (which is based on proactor pattern) is one such option. NIO2(基于前摄器模式)就是这样一种选择。 But the underlying architecture is very different to original NIO. 但是底层架构与原始NIO有很大不同。

the basic idea of this is to split the task : 其基本思想是拆分任务

    ExecuterService workers = Executors.newFixedThreadPool(50);

    ....
    while (true) {

                this.selector.select();

                Iterator keys = this.selector.selectedKeys().iterator();
                while (keys.hasNext()) {
                    SelectionKey key = (SelectionKey) keys.next();

                    keys.remove();

                    if (! key.isValid()) {
                        continue;
                    }

                    if (key.isAcceptable()) {
                        this.accept(key);
                    }
                    else if (key.isReadable()) {
                        workers.execute(new ReadTaskHandler(key));
                    }
                    else if (key.isWritable()) {
                        workers.execute(new WriteTaskHandler(key));
                    }
                }
            }
class ReadTaskHandler implements Runnable {
    SelectionKey key;

    public ReadTaskHandler(SelectionKey key) {
        this.key = key;
    }

    @Override
    public void run() {
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        SocketChannel channel = (SocketChannel) key.channel();

        int size = 0;
        try {
            while ((size = channel.read(buffer)) > 0) {
                System.out.println(new String(buffer.array()));
                buffer.flip();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

In fact, there are many models about NIO. 实际上,关于NIO的模型很多。 For example, we can also use multiple threads to handle the accept task(also called multiple reactors model or multiple eventloop model). 例如,我们还可以使用多个线程来处理接受任务(也称为多个反应堆模型或多个事件循环模型)。

BTW, Netty is a great event-driven network application framework packaged java NIO 顺便说一句,Netty是一个伟大的事件驱动的网络应用程序框架,打包为Java NIO

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM