Scalable IO in Java的代码实现

    xiaoxiao2021-03-25  89

            最近在学习NIO相关的知识部分,在学习的时候,发现Doug Lea大神的一个PPT地址,里面的内容写的非常好,

    很值得学习,具体内容可以参见PPT和网上的文章,自己根据PPT中的例子和描述,自己将代码补充了一下。下面主要是PPT中的代码和实例。

    1.Basic Reactor Design

    package basic; import java.io.IOException; import java.net.InetSocketAddress; 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.util.Iterator; import java.util.Set; /** * @ClassName: Reactor * @Description: 根据 Scalable IO in Java写的实例。 * @date 2017年3月7日 */ 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()); } public void run() { try{ while(!Thread.interrupted()){ int n = selector.select();//等待事件 if(n == 0) continue; Set<SelectionKey> set = selector.selectedKeys(); Iterator<SelectionKey> iterator = set.iterator(); while(iterator.hasNext()){ dispatch(iterator.next()); } set.clear(); } }catch(Exception e){ e.printStackTrace(); } } private void dispatch(SelectionKey k) { Runnable runnable = (Runnable) k.attachment(); if(runnable != null) runnable.run(); } class Acceptor implements Runnable { public void run() { try { SocketChannel c = serverSocketChannel.accept();//接收请求 if(c != null){ System.out.println("New Connection ..."); new Handler(selector, c); } } catch (IOException e) { e.printStackTrace(); } } } final class Handler implements Runnable{ final SocketChannel socket; final SelectionKey key; ByteBuffer input = ByteBuffer.allocate(1024); ByteBuffer output = ByteBuffer.allocate(1024); static final int READING = 0,SENDING =1; int state = READING; public Handler(Selector selector, SocketChannel c) throws IOException { socket = c; socket.configureBlocking(false); key = socket.register(selector, 0); key.attach(this); key.interestOps(SelectionKey.OP_READ);//注册可读事件 selector.wakeup(); } public void run() { try { if(state == READING) read(); else if(state == SENDING) send(); } catch (Exception e) { e.printStackTrace(); } } boolean inputIsComplete(){ return input.hasRemaining(); } boolean outputIsComplete(){ return output.hasRemaining(); } void process(){ //读数据 StringBuilder reader = new StringBuilder(); input.flip(); while(input.hasRemaining()){ reader.append((char)input.get()); } System.out.println("[Client-INFO]"); System.out.println(reader.toString()); String str = "HTTP/1.1 200 OK\r\nDate: Fir, 10 March 2017 21:20:01 GMT\r\n"+ "Content-Type: text/html;charset=UTF-8\r\nContent-Length: 23\r\nConnection:close"+ "\r\n\r\nHelloWorld"+System.currentTimeMillis(); output.put(str.getBytes()); System.out.println("process over.... "); } void read() throws IOException{ socket.read(input); if(inputIsComplete()){ process(); state = SENDING; key.interestOps(SelectionKey.OP_WRITE); } } void send() throws IOException { output.flip(); socket.write(output); if(outputIsComplete()){ key.cancel(); } state = READING; key.interestOps(SelectionKey.OP_READ); } } public static void main(String[] args) throws IOException { new Thread(new Reactor(9001)).start(); System.out.println("Server start..."); } }

    2.Per-State Handlers

    package state; import java.io.IOException; import java.net.InetSocketAddress; 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.util.Iterator; import java.util.Set; /** * @ClassName: Reactor * @Description: 根据 Scalable IO in Java写的实例。 * @author Lzyer * @date 2017年3月7日 */ 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()); } public void run() { try{ while(!Thread.interrupted()){ int n = selector.select();//等待事件 if(n == 0) continue; Set<SelectionKey> set = selector.selectedKeys(); Iterator<SelectionKey> iterator = set.iterator(); while(iterator.hasNext()){ dispatch(iterator.next()); } set.clear(); } }catch(Exception e){ e.printStackTrace(); } } private void dispatch(SelectionKey k) { Runnable runnable = (Runnable) k.attachment(); if(runnable != null) runnable.run(); } class Acceptor implements Runnable { public void run() { try { SocketChannel c = serverSocketChannel.accept(); if(c != null){ System.out.println("New Connection ..."); new Handler2(selector, c); } } catch (IOException e) { e.printStackTrace(); } } } /*** * @ClassName: Handler2 * @Description: State-Object pattern * @author lzyer * @date 2017年3月8日 * */ class Handler2 implements Runnable{ final SocketChannel socket; final SelectionKey key; ByteBuffer input = ByteBuffer.allocate(1024); ByteBuffer output = ByteBuffer.allocate(1024); static final int READING = 0,SENDING =1; int state = READING; public Handler2(Selector selector, SocketChannel c) throws IOException { this.socket = c; this.socket.configureBlocking(false); key = socket.register(selector, SelectionKey.OP_READ); key.attach(this); selector.wakeup(); } public void run() { try { socket.read(input); if(inputIsComplete()){ process(); key.attach(new Sender());//send thread key.interestOps(SelectionKey.OP_WRITE); key.selector().wakeup(); } } catch (IOException e) { e.printStackTrace(); } } boolean inputIsComplete(){ return input.hasRemaining(); } boolean outputIsComplete(){ return output.hasRemaining(); } void process(){ //读数据 StringBuilder reader = new StringBuilder(); input.flip(); while(input.hasRemaining()){ reader.append((char)input.get()); } System.out.println("[Client-INFO]"); System.out.println(reader.toString()); String str = "HTTP/1.1 200 OK\r\nDate: Sat, 31 Dec 2005 23:59:59 GMT\r\n"+ "Content-Type: text/html;charset=UTF-8\r\nContent-Length: 23\r\nConnection:close"+ "\r\n\r\nWelcome NIO "+System.currentTimeMillis(); output.put(str.getBytes()); System.out.println("process over.... "); } class Sender implements Runnable{ public void run() { try { output.flip(); socket.write(output); if(outputIsComplete()) key.cancel(); socket.close();//记住要关闭 } catch (IOException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws IOException { new Thread(new Reactor(9001)).start(); System.out.println("Server start..."); } }

    3.Handler with Thread Pool

    package pool; import java.io.IOException; import java.net.InetSocketAddress; 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.util.Iterator; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @ClassName: Reactor * @Description: 根据 Scalable IO in Java写的实例。 * @author Lzyer * @date 2017年3月7日 */ 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()); } public void run() { try{ while(!Thread.interrupted()){ int n = selector.select(); if(n == 0) continue; Set<SelectionKey> set = selector.selectedKeys(); Iterator<SelectionKey> iterator = set.iterator(); while(iterator.hasNext()){ dispatch(iterator.next()); } set.clear(); } }catch(Exception e){ e.printStackTrace(); } } private void dispatch(SelectionKey k) { Runnable runnable = (Runnable) k.attachment(); if(runnable != null) runnable.run(); } class Acceptor implements Runnable { public void run() { try { SocketChannel c = serverSocketChannel.accept(); if(c != null){ System.out.println("New Connection ..."); new Handler3(selector, c); } } catch (IOException e) { e.printStackTrace(); } } } /** * @ClassName: Handler3 * @Description: 使用线程池 * @author Lzyer * @date 2017年3月8日 * */ class Handler3 implements Runnable { final SocketChannel socket; final SelectionKey key; ByteBuffer input = ByteBuffer.allocate(1024); ByteBuffer output = ByteBuffer.allocate(1024); static final int READING = 0,SENDING =1, PROCESSING =3; int state = READING; ExecutorService pool = Executors.newCachedThreadPool(); public Handler3(Selector selector, SocketChannel c) throws IOException { this.socket = c; this.socket.configureBlocking(false); key = socket.register(selector, SelectionKey.OP_READ); key.attach(this); selector.wakeup(); } public void run() { try { if(state == READING) read(); else if(state == SENDING) send(); } catch (IOException e) { e.printStackTrace(); } } synchronized void read() throws IOException { socket.read(input); if (inputIsComplete()) { state = PROCESSING; pool.execute(new Processer()); } } void send() throws IOException { output.flip(); socket.write(output); if(outputIsComplete()){ key.cancel(); } state = READING; key.interestOps(SelectionKey.OP_READ); } void process(){ //读数据 StringBuilder reader = new StringBuilder(); input.flip(); while(input.hasRemaining()){ reader.append((char)input.get()); } System.out.println("[Client-INFO]"); System.out.println(reader.toString()); String str = "HTTP/1.1 200 OK\r\nDate: Fir, 10 March 2017 21:20:01 GMT\r\n"+ "Content-Type: text/html;charset=UTF-8\r\nContent-Length: 32\r\nConnection:close"+ "\r\n\r\nWelcome JAVA World "+System.currentTimeMillis(); output.put(str.getBytes()); System.out.println("process .... "); } boolean inputIsComplete(){ return input.hasRemaining(); } boolean outputIsComplete(){ return output.hasRemaining(); } synchronized void processAndHandOff() { process(); state = SENDING; // or rebind attachment key.interestOps(SelectionKey.OP_WRITE); System.out.println("processer over...."); } class Processer implements Runnable { public void run() { processAndHandOff(); } } } public static void main(String[] args) throws IOException { new Thread(new Reactor(9001)).start(); System.out.println("Server start..."); } }

    4Using Multiple Reactors

    package multiple; import java.io.IOException; import java.util.concurrent.atomic.AtomicInteger; public class Server { private static Reactor mainReactor;//主要负责接收请求 private static Reactor[] subReactors;//负责处理IO private static final int SUB_SIZE = 3; private static final int port = 1234; private static AtomicInteger nextIndex = new AtomicInteger(); public static Reactor nextSubReactor(){ long nextIndexValue = nextIndex.getAndIncrement(); if(nextIndexValue < 0){ nextIndex.set(0); nextIndexValue = 0; } return subReactors[(int) (nextIndexValue%subReactors.length)]; } public static void main(String[] args) { try { mainReactor = new Reactor(port, true); subReactors = new Reactor[SUB_SIZE]; for(int i=0; i< subReactors.length; i++){ subReactors[i] = new Reactor(port, false); } mainReactor.start(); for(int i=0; i< subReactors.length; i++){ subReactors[i].start(); } } catch (IOException e) { e.printStackTrace(); } } }

    package multiple; 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.util.Iterator; /** * @ClassName: Reactor * @Description: 根据 Scalable IO in Java写的实例。 * @author Lzyer * @date 2017年3月10日 */ public class Reactor extends Thread { final Selector selector; final boolean isMain;//主从的标志 public Reactor(int port, boolean isMain) throws IOException { this.isMain = isMain; selector = Selector.open(); System.out.println(selector +" isMainReactor = "+isMain); if(isMain){ ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.socket().bind(new InetSocketAddress(port)); serverSocketChannel.configureBlocking(false); SelectionKey key = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); key.attach(new Acceptor(selector, serverSocketChannel)); selector.wakeup(); System.out.println(getClass().getSimpleName()+" start on "+port+" ...\n"); } } public void run() { try { while(!Thread.interrupted()){ int n = selector.select(10);//会阻塞导致不能register,设置阻塞时间 if(n == 0) continue; Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while(iterator.hasNext()){ dispatch(iterator.next()); iterator.remove(); } } } catch (IOException e) { e.printStackTrace(); } } private void dispatch(SelectionKey k) { Runnable runnable = (Runnable) k.attachment(); if(runnable != null) runnable.run(); } }

    package multiple; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; /** * @ClassName: Acceptor * @Description: 接收请求 * @author Lzyer * @date 2017年3月9日 * */ public class Acceptor implements Runnable { private ServerSocketChannel serverSocketChannel; private Selector selector; public Acceptor(Selector selector,ServerSocketChannel ser) { this.selector = selector; this.serverSocketChannel = ser; } public void run() { try{ System.out.println(selector+" accept ...."); SocketChannel socketChannel = serverSocketChannel.accept(); if(socketChannel != null){ /** * 开启了多个reactor池,一个selector负责接收和处理IO * new Handler(selector, socketChannel); */ //使用的主从结构,一个主selector负责接收,其他的负责处理IO Selector selector2 = Server.nextSubReactor().selector; System.out.println(selector2+" clientChannel not null..."+socketChannel); new Handler(selector2, socketChannel); } }catch(Exception e){ e.printStackTrace(); } } }

    package multiple; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; /** * @ClassName: Handler * @Description: 处理IO操作 * @author Lzyer * @date 2017年3月9日 * */ public class Handler implements Runnable { final SocketChannel socket; final SelectionKey key; ByteBuffer input = ByteBuffer.allocate(1024); ByteBuffer output = ByteBuffer.allocate(1024); static final int READING = 0,SENDING =1; int state = READING; public Handler(Selector selector, SocketChannel c) throws IOException { socket = c; socket.configureBlocking(false); key = socket.register(selector,SelectionKey.OP_READ); key.attach(this); selector.wakeup(); System.out.println(selector+" connect success..."); } public void run() { try { if(state == READING) read(); else if(state == SENDING) send(); } catch (Exception e) { e.printStackTrace(); } } boolean inputIsComplete(){ return input.hasRemaining(); } boolean outputIsComplete(){ return output.hasRemaining(); } void process(){ //读数据 StringBuilder reader = new StringBuilder(); input.flip(); while(input.hasRemaining()){ reader.append((char)input.get()); } System.out.println("[Client-INFO]"); System.out.println(reader.toString()); String str = "HTTP/1.1 200 OK\r\nDate: Fir, 10 March 2017 21:20:01 GMT\r\n"+ "Content-Type: text/html;charset=UTF-8\r\nContent-Length: 24\r\nConnection:close"+ "\r\n\r\nHelloRector"+System.currentTimeMillis(); output.put(str.getBytes()); System.out.println("process .... "); } void read() throws IOException{ socket.read(input); if(inputIsComplete()){ process(); state = SENDING; key.interestOps(SelectionKey.OP_WRITE); } } void send() throws IOException { output.flip(); socket.write(output); if(outputIsComplete()){ key.cancel(); } state = READING; key.interestOps(SelectionKey.OP_READ); } }

    代码地址:链接

    参考:http://blog.csdn.net/jjzhk/article/details/39553613

           http://www.iclojure.com/blog/articles/2015/12/05/Scalable-IO-in-Java

    转载请注明原文地址: https://ju.6miu.com/read-25082.html

    最新回复(0)