NIO selector multiplexer reactor threading model

NIO selector multiplexer reactor threading model
package com.study.hc.net.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * NIO selector 多路复用reactor线程模型
 * / 
Public  class NIOServerV3 {
     / ** threading business operations * / 
    Private  static ExecutorService workPool = Executors.newCachedThreadPool (); 

    / ** 
     * encapsulates the selector.select () like polling event code 
     * / 
    abstract  class ReactorThread the extends {the Thread 

        Selector Selector; 
        a LinkedBlockingQueue <the Runnable> = taskqueue new new a LinkedBlockingQueue <> (); 

        / ** 
         * Selector monitored an event after calling this method 
         * / 
        public  abstract  void Handler (a SelectableChannel Channel) throwsException; 

        Private ReactorThread () throws IOException { 
            Selector = Selector.open (); 
        } 

        volatile  Boolean running = to false ; 

        @Override 
        public  void RUN () {
             // polling event Selector 
            the while (running) {
                 the try {
                     // perform queue the task of 
                    the Runnable task;
                     the while (! (task taskQueue.poll = ()) = null ) { 
                        task.run (); 
                    }
                    the selector.select ( 1000 ); 

                    // Get the query result 
                    the Set <the SelectionKey> Selected = selector.selectedKeys ();
                     // iterate the query result 
                    the Iterator <the SelectionKey> ITER = selected.iterator ();
                     the while (iter.hasNext ()) {
                         // encapsulated query results 
                        SelectionKey Key = iter.next (); 
                        iter.remove (); 
                        int readyOps = key.readyOps ();
                         // attention Read and Accept two events 
                        if(! (the readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) = 0 || the readyOps == 0 ) {
                             the try { 
                                a SelectableChannel Channel = (a SelectableChannel) key.attachment (); 
                                channel.configureBlocking ( to false ); 
                                Handler (Channel) ; 
                                IF (! {channel.isOpen ()) 
                                    key.cancel (); // if closed, to the unsubscribed KEY 
                                } 
                            } the catch (Exception EX) { 
                                key.cancel ();// If an exception, to cancel the subscription KEY 
                            } 
                        } 
                    } 
                    selector.selectNow (); 
                } the catch (IOException E) { 
                    e.printStackTrace (); 
                } 
            } 
        } 

        Private the SelectionKey Register (a SelectableChannel Channel) throws Exception {
             // Why to register in the form of job submission, so that reactor thread to handle?
            // thread because the thread performing channel selector in the process of registering to, and will call selector.select () method of the same lock contention
             // The select () method call it cycle through while in eventLoop, the competition may high, in order to allow faster execution register, put it to deal with the same thread
            FutureTask<SelectionKey> futureTask = new FutureTask<>(() -> channel.register(selector, 0, channel));
            taskQueue.add(futureTask);
            return futureTask.get();
        }

        private void doStart() {
            if (!running) {
                running = true;
                start();
            }
        }
    }

    private ServerSocketChannel serverSocketChannel;
    // 1、创建多个线程 - accept处理reactor线程 (accept线程)
    private ReactorThread[] mainReactorThreads = newReactorThread [. 1 ];
     // 2, create multiple threads - io thread processing reactor (I / O threads) 
    Private ReactorThread [] = subReactorThreads new new ReactorThread [. 8 ]; 

    / ** 
     * initialize the thread group 
     * / 
    Private  void newGroup, () throws IOException {
         // create IO thread, handles the client after the connection of the IO write socketChannel 
        for ( int I = 0; I <subReactorThreads.length; I ++ ) { 
            subReactorThreads [I] = new new ReactorThread () { 
                @Override 
                public  void Handler (SelectableChannel Channel) throws{IOException
                     // Work thread only handles IO process, not an event handling accept 
                    SocketChannel CH = (SocketChannel) Channel; 
                    ByteBuffer requestBuffer = ByteBuffer.allocate (1024 );
                     the while (ch.isOpen () && ch.read (requestBuffer) =! -1 ) {
                         // the length of connection, there is no need to manually read end data is determined (here make a simple determination: over 0 bytes is considered the end of the request) 
                        IF (requestBuffer.position ()> 0) BREAK ; 
                    } 
                    IF (requestBuffer.position () == 0) return ; // If there is no data, the subsequent processing is not continued
                    requestBuffer.flip ();
                     byte [] Content = new new  byte [requestBuffer.limit ()]; 
                    requestBuffer.get (Content); 
                    System.out.println ( new new String (Content)); 
                    System.out.println (Thread.currentThread () .getName () + "receives data from:" + ch.getRemoteAddress ()); 

                    // the TODO operational databases, interfaces ... 
                    workPool.submit (() -> { 
                    }); 

                    // response result 200 is 
                    String = Response "the HTTP / 1.1 200 is the OK \ R & lt \ n-" + 
                            "the Content-the Length:. 11 \ R & lt \ n-\ R & lt \ n-" + 
                            "the Hello World" ;
                    ByteBuffer buffer = ByteBuffer.wrap(response.getBytes());
                    while (buffer.hasRemaining()) {
                        ch.write(buffer);
                    }
                }
            };
        }

        // 创建mainReactor线程, 只负责处理serverSocketChannel
        for (int i = 0; i < mainReactorThreads.length; i++) {
            mainReactorThreads[i] = new ReactorThread() {
                AtomicInteger incr = new AtomicInteger(0);

                @Override 
                public  void Handler (a SelectableChannel Channel) throws Exception {
                     // only request distribution, specific data is not read 
                    a ServerSocketChannel CH = (a ServerSocketChannel) Channel; 
                    the SocketChannel SocketChannel = ch.accept (); 
                    socketChannel.configureBlocking ( to false );
                     // after notification of the connection establishment, distributed I / O thread continues to read data 
                    int index = incr.getAndIncrement ()% subReactorThreads.length; 
                    ReactorThread workEventLoop = subReactorThreads [index];
                    workEventLoop.doStart (); 
                    the SelectionKey SelectionKey = workEventLoop.register (SocketChannel); 
                    selectionKey.interestOps (SelectionKey.OP_READ); 
                    System.out.println (Thread.currentThread () getName (). + "receive new connection:" + socketChannel.getRemoteAddress ()); 
                } 
            }; 
        } 


    } 

    / ** 
     * initialize the channel, and a binding thread eventLoop 
     * 
     * @throws IOException the IO exception
      * / 
    Private  void initAndRegister () throws exception {
         // . 1, creating ServerSocketChannel 
        ServerSocketChannel = ServerSocketChannel.open ();
        serverSocketChannel.configureBlocking(false);
        // 2、 将serverSocketChannel注册到selector
        int index = new Random().nextInt(mainReactorThreads.length);
        mainReactorThreads[index].doStart();
        SelectionKey selectionKey = mainReactorThreads[index].register(serverSocketChannel);
        selectionKey.interestOps(SelectionKey.OP_ACCEPT);
    }

    /**
     * 绑定端口
     *
     * @throws IOException IO异常
     */
    private void bind() throws{IOException
         //  1, formally bound port, external services 
        serverSocketChannel.bind ( new new InetSocketAddress (8080 )); 
        System.out.println ( "startup is complete, port 8080" ); 
    } 

    public  static  void main (String [] args) throws Exception { 
        NIOServerV3 nioServerV3 = new new NIOServerV3 (); 
        nioServerV3.newGroup (); // 1, create main and sub two threads 
        nioServerV3.initAndRegister (); // 2, create serverSocketChannel, registered on the selector on mainReactor thread 
        nioServerV3.bind () ; // 3, port bindings for the serverSocketChannel 
    } 
}

Guess you like

Origin www.cnblogs.com/itbac/p/12046893.html