`
ryanflyer
  • 浏览: 101022 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

NIO Reactor模式(阅读NIO笔记)

阅读更多

注:内容均节选自附件中的ppt文档。

 

1.网络服务一般的结构:

  读取请求--->解码请求--->处理服务--->编码响应--->发送响应

经典的服务设计是“每一个请求一个线程”,如下图



 2.Reactor模式

Reactor响应I/O事件,分发到合适的Handler处理。

Handler执行非阻塞的动作。

基本的Reactor设计,单线程版本


示例代码:

 

package com.zhang.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Set;

public class Reactor implements Runnable {

    final Selector selector;

    final ServerSocketChannel serverSocketChannel;

    public Reactor(int port) throws IOException {
        selector = Selector.open();
        serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(port));
        serverSocketChannel.configureBlocking(false);
        SelectionKey key = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        key.attach(new Acceptor());
    }

    @Override
    public void run() {
        while (!Thread.interrupted()) {
            try {
                selector.select();
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                for(SelectionKey selectionKey : selectionKeys){
                    dispatch(selectionKey);
                }
                selectionKeys.clear();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

    private void dispatch(SelectionKey selectionKey) {
        Runnable run = (Runnable) selectionKey.attachment();
        if(run != null){
            run.run();
        }
    }
    
    class Acceptor implements Runnable{

        @Override
        public void run() {
            try {
                SocketChannel channel = serverSocketChannel.accept();
                if(channel != null){
                    new Handler(selector,channel);
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }

    }

}
 

 

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;

public class Handler implements Runnable {

    private final static int DEFAULT_SIZE = 8092;

    private final SocketChannel socketChannel;

    private final SelectionKey seletionKey;

    private static final int READING = 0;

    private static final int SENDING = 1;
    
    private int state = READING;

    ByteBuffer inputBuffer = ByteBuffer.allocate(DEFAULT_SIZE);

    ByteBuffer outputBuffer = ByteBuffer.allocate(DEFAULT_SIZE);

    public Handler(Selector selector, SocketChannel channel) throws IOException {
        this.socketChannel = channel;
        socketChannel.configureBlocking(false);
        this.seletionKey = socketChannel.register(selector, 0);
        seletionKey.attach(this);
        seletionKey.interestOps(SelectionKey.OP_READ);
        selector.wakeup();
    }

    @Override
    public void run() {
        if(state == READING){
            read();
        }else if(state == SENDING){
            write();
        }

    }
    
    class Sender implements Runnable {

        @Override
        public void run() {
            try {
                socketChannel.write(outputBuffer);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            if(outIsComplete()){
                seletionKey.cancel();
            }
            
            
        }
        
    }

    private void write() {
        try {
            socketChannel.write(outputBuffer);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        while(outIsComplete()){
            seletionKey.cancel();
        }
        
    }

    private void read() {
        try {
            socketChannel.read(inputBuffer);
            if(inputIsComplete()){
                process();
                seletionKey.attach(new Sender());
                seletionKey.interestOps(SelectionKey.OP_WRITE);
                seletionKey.selector().wakeup();
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        
    }
    
    public boolean inputIsComplete(){
        return false;
    }
    
    public boolean outIsComplete(){
        return false;
        
    }
    
    public void process(){
        
    }

}
 

NIO支持的特性:

 

  • Channels,连接到文件、socket等等,支持非阻塞读。
  • Buffers,与数组相似的对象,能直接从Channels中读写。
  • Selectors,辨识哪一个通道的集合有IO事件。(Tell which of a set of Channels have IO events)
  • SelectionKeys,维护IO事件的状态和绑定。
多线程设计
  • 添加线程增加可扩展性,主要应用在多核处理器中
  • Worker 线程,Reactors要快速出发handlers。handlers的处理降低了Reactor的速度。将非I/O操作分离到其他线程中处理。
  • Multiple Reactor Threads,多Reactor线程。Reactor线程可以使IO操作饱和,分布负载到其他的reactors,负载均衡来匹配CPU和IO之间的速度差异。


 使用多个Reactors


 

 

  • nio.pdf (270.6 KB)
  • 下载次数: 182
  • 大小: 45 KB
  • 大小: 44.6 KB
  • 大小: 101.1 KB
  • 大小: 110.8 KB
分享到:
评论
2 楼 Jnerd 2014-01-20  
Handler初始化的应该注册read,否则select就会阻塞,而因为你的wakeup跑完整个程序。
1 楼 Jnerd 2014-01-20  
运行了不正确呢

相关推荐

    java基于NIO实现Reactor模型源码.zip

    java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现...

    Reactor模式和NIO

    Reactor模式和NIO Java的NIO为reactor模式提供了实现的基础机制,它的Selector当发现某个channel有数据时,会通过SlectorKey来告知我们,在此我们实现事件和handler的绑定

    java nio and reactor

    java nio 作者的ppt。 How to Build a Scalable Multiplexed Server With NIO 文中讲述如何使用java nio来实现高性能的服务器。...2、java nio 和 reactor 的映射关系 3、如果使用java nio 来实现高性能服务器

    NIO笔记.doc

    NIO笔记.doc

    深入浅出NIO

    NIO 入门笔记 Reactor模式概念介绍

    reactor:NIO 编程模型 - Reactor,各版本实现

    依据 Doug Lea 的 基于 NIO 实现的 Reacotr 模式的回显服务器 BasicHandler: 单线程处理器 MultiReactor: 主从 Reactor MultithreadHandler: 线程池处理器 Reactor: 接收连接,I/O 读写 Reactor 模型的说明: ...

    nioreactor:无阻塞IOReact器

    由于React堆线程可以在执行IO时饱和,因此nioreactor使用接受器线程将新连接转发到可以在非阻塞模式下处理读取和写入的React堆池。 建筑分布 要求 2.2.0或以上 Java 8或以上 建立: git clone mvn clean install ...

    java学习笔记1(java io/nio)

    java学习笔记1(java io/nio)设计模式

    socket通信NIO代理模式demo实例

    socket通信nio模式有很多实现方式,但是在性能上、资源上一般很少考虑,这里封装了一个性能极强的程序。

    基于Java NIO反应器模式设计与实现

    Java NIO反应器模式讲解,目前热门的Java网络通信框架中Mina,Netty等都采用NIO

    socket-nio-single-reactor.zip

    reactor多线程,java代码demo,帮助理解reactor模式;由于是测试代码,故不保证一定正确,能正常接入传输数据,目前数据包处理没做,故会出现数据截断

    java NIO socket聊天室

    可以作为NIO socket入门的例子,Reactor模式,重点理解key.attach, jar文件里包含了源代码 1,运行server.bat启动服务器,可以打开编辑,修改端口号 2,运行client.bat启动客户端,可以打开编辑,ip,和端口号 3...

    Nio学习笔记(java)

    Nio学习笔记

    javaNIO学习笔记

    java NIO的基本知识点学习笔记,不包含具体代码

    JavaNIO chm帮助文档

    Java NIO系列教程(一) Java NIO 概述 Java NIO系列教程(二) Channel Java NIO系列教程(三) Buffer Java NIO系列教程(四) Scatter/Gather Java NIO系列教程(五) 通道之间的数据传输 Java NIO系列教程(六)...

    nio demo for nio学习笔记(体系结构以及模块介绍)

    文章同步:http://blog.csdn.net/wgyscsf/article/details/50953318

    java NIO和java并发编程的书籍

    java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java...

    NIO 入门.chm,NIO 入门.chm

    NIO入门.chm NIO入门.chm NIO入门.chm

    java nio 包读取超大数据文件

    Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据...

    从Jetty、Tomcat和Mina中提炼NIO构架网络服务器的经典模式

    从Jetty、Tomcat和Mina中提炼NIO构架网络服务器的经典模式.doc

Global site tag (gtag.js) - Google Analytics