ITPub博客

首页 > 应用开发 > Java > Reactor模式

Reactor模式

原创 Java 作者:壹頁書 时间:2017-06-22 14:41:57 0 删除 编辑
青木大师
https://github.com/goudai/gd-rpc

在这个基础上,抽取的Reactor模式 简化理解的版本
这个JAVA nio和多线程结合的问题,已经困扰了好几年了.
通过阅读青木的代码,终于有点明白了


  1. import java.io.BufferedReader;  
  2. import java.io.IOException;  
  3. import java.io.InputStreamReader;  
  4. import java.net.InetSocketAddress;  
  5. import java.net.Socket;  
  6. import java.net.StandardSocketOptions;  
  7. import java.nio.ByteBuffer;  
  8. import java.nio.CharBuffer;  
  9. import java.nio.channels.ClosedChannelException;  
  10. import java.nio.channels.SelectionKey;  
  11. import java.nio.channels.Selector;  
  12. import java.nio.channels.ServerSocketChannel;  
  13. import java.nio.channels.SocketChannel;  
  14. import java.nio.charset.Charset;  
  15. import java.text.SimpleDateFormat;  
  16. import java.util.Date;  
  17. import java.util.Iterator;  
  18. import java.util.Queue;  
  19. import java.util.Set;  
  20. import java.util.concurrent.ConcurrentLinkedQueue;  
  21. import java.util.concurrent.atomic.AtomicInteger;  
  22.   
  23. class NIOTest {  
  24.     public static void main(String[] args) throws IOException {  
  25.         Acceptor acceptor = new Acceptor(9090, new Reactor(10));  
  26.         acceptor.start();  
  27.   
  28.         Socket socket = new Socket("127.0.0.1", 9090);  
  29.   
  30.         socket.getOutputStream().write("helloworld\n".getBytes());  
  31.         socket.getOutputStream().write("helloworld\n".getBytes());  
  32.         socket.getOutputStream().write("helloworld\n".getBytes());  
  33.         socket.getOutputStream().flush();  
  34.         BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
  35.         String str = null;  
  36.         while ((str = br.readLine()) != null) {  
  37.             System.out.println(str);  
  38.         }  
  39.   
  40.         socket.close();  
  41.     }  
  42. }  
  43.   
  44. class Reactor {  
  45.     private final Worker[] workers;  
  46.     private final int workerCount;  
  47.     private final static AtomicInteger SELECTORINDEX = new AtomicInteger();  
  48.   
  49.     public Reactor(int workerCount) throws IOException {  
  50.         this.workerCount = workerCount;  
  51.         this.workers = new Worker[workerCount];  
  52.         for (int i = 0; i < workerCount; i++) {  
  53.             workers[i] = new Worker("worker_" + i);  
  54.             workers[i].start();  
  55.         }  
  56.     }  
  57.   
  58.     public void register(SocketChannel socket) {  
  59.         Channel channel = new Channel(socket, SelectionKey.OP_READ);  
  60.   
  61.         this.workers[SELECTORINDEX.getAndIncrement() % this.workerCount].register(channel);  
  62.     }  
  63.   
  64.     class Worker extends Thread {  
  65.   
  66.         private final Selector selector;  
  67.         private final String name;  
  68.         private final Queue<Channel> asyncRegistrySocketChannels = new ConcurrentLinkedQueue<Channel>();  
  69.         private final Charset charset;  
  70.         private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  71.   
  72.         public Worker(String name) throws IOException {  
  73.             this.name = name;  
  74.             this.charset = Charset.forName("utf8");  
  75.             selector = Selector.open();  
  76.         }  
  77.   
  78.         public void register(Channel channel) {  
  79.             this.asyncRegistrySocketChannels.offer(channel);  
  80.             this.selector.wakeup();  
  81.         }  
  82.   
  83.         private void asyncRegister() throws ClosedChannelException {  
  84.             Channel channel = null;  
  85.             while ((channel = asyncRegistrySocketChannels.poll()) != null) {  
  86.                 channel.getSocketChannel().register(selector, SelectionKey.OP_READ);  
  87.             }  
  88.         }  
  89.   
  90.         @Override  
  91.         public void run() {  
  92.             while (true) {  
  93.   
  94.                 try {  
  95.                     asyncRegister();  
  96.                     selector.select();  
  97.                     Set<SelectionKey> selectionKeys = this.selector.selectedKeys();  
  98.                     for (SelectionKey key : selectionKeys) {  
  99.                         if (key.isValid() && key.isReadable()) {  
  100.                             Object obj = key.attachment();  
  101.                             SocketChannel channel = (SocketChannel) key.channel();  
  102.                             StringBuilder sb;  
  103.                             if (obj == null) {  
  104.                                 sb = new StringBuilder();  
  105.                             } else {  
  106.                                 sb = (StringBuilder) obj;  
  107.                             }  
  108.                             ByteBuffer bb = ByteBuffer.allocate(1024);  
  109.                             int count = 0;  
  110.                             while ((count = channel.read(bb)) > 0) {  
  111.                                 bb.flip();  
  112.                                 CharBuffer cb = charset.decode(bb);  
  113.                                 sb.append(cb.toString());  
  114.                                 bb.compact();  
  115.                             }  
  116.                             if (sb.charAt(sb.length() - 1) != '\n') {  
  117.                                 channel.register(selector, SelectionKey.OP_READ, sb);  
  118.                             } else {  
  119.                                 channel.register(selector, SelectionKey.OP_WRITE, sb);  
  120.                             }  
  121.   
  122.                         } else if (key.isValid() && key.isWritable()) {  
  123.                             StringBuilder sb = (StringBuilder) key.attachment();  
  124.                             SocketChannel channel = (SocketChannel) key.channel();  
  125.                             for (String s : sb.toString().split("\n")) {  
  126.                                 String str = sdf.format(new Date()) + ":" + s + "\n";  
  127.                                 channel.write(ByteBuffer.wrap(str.toString().getBytes()));  
  128.                             }  
  129.                             channel.register(selector, SelectionKey.OP_READ, null);  
  130.                         }  
  131.                     }  
  132.                     selectionKeys.clear();  
  133.                 } catch (IOException e) {  
  134.                     e.printStackTrace();  
  135.                 }  
  136.   
  137.             }  
  138.         }  
  139.     };  
  140.   
  141.     class Channel {  
  142.         public SocketChannel getSocketChannel() {  
  143.             return socketChannel;  
  144.         }  
  145.   
  146.         public void setSocketChannel(SocketChannel socketChannel) {  
  147.             this.socketChannel = socketChannel;  
  148.         }  
  149.   
  150.         public int getOps() {  
  151.             return ops;  
  152.         }  
  153.   
  154.         public void setOps(int ops) {  
  155.             this.ops = ops;  
  156.         }  
  157.   
  158.         public Channel(SocketChannel socketChannel, int ops) {  
  159.             this.socketChannel = socketChannel;  
  160.             this.ops = ops;  
  161.         }  
  162.   
  163.         private SocketChannel socketChannel;  
  164.         private int ops;  
  165.   
  166.     }  
  167. }  
  168.   
  169. class Acceptor extends Thread {  
  170.     private final Selector selector;  
  171.     private final Reactor reactor;  
  172.     private final ServerSocketChannel serverSocketChannel;  
  173.   
  174.     public Acceptor(int port, Reactor reactor) throws IOException {  
  175.         this.selector = Selector.open();  
  176.         this.reactor = reactor;  
  177.         this.serverSocketChannel = (ServerSocketChannel) ServerSocketChannel.open().bind(new InetSocketAddress(port))  
  178.                 .configureBlocking(false);  
  179.         this.serverSocketChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);  
  180.         this.serverSocketChannel.setOption(StandardSocketOptions.SO_RCVBUF, 1024 * 16 * 2);  
  181.         this.serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);  
  182.     }  
  183.   
  184.     @Override  
  185.     public void run() {  
  186.         while (true) {  
  187.             try {  
  188.                 int i = selector.select();  
  189.                 if (i > 0) {  
  190.                     Iterator<SelectionKey> it = selector.selectedKeys().iterator();  
  191.                     SelectionKey key = it.next();  
  192.                     if (key.isValid() && key.isAcceptable()) {  
  193.                         ServerSocketChannel server = (ServerSocketChannel) key.channel();  
  194.                         SocketChannel socket = server.accept();  
  195.                         socket.configureBlocking(false);  
  196.                         reactor.register(socket);  
  197.                     } else {  
  198.                         key.cancel();  
  199.                     }  
  200.                 }  
  201.             } catch (IOException e) {  
  202.                 e.printStackTrace();  
  203.             }  
  204.         }  
  205.     }  
  206.   
  207. } 

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29254281/viewspace-2141129/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2013-10-19

  • 博文量
    620
  • 访问量
    6339882