Java 杂谈 Java-填坑之路

BIO、NIO、AIO的区别

2018-06-26  本文已影响8人  IT5

BIO:线程发起IO请求,不管内核是否准备好IO操作,从发起请求起,线程一直阻塞,直到操作完成。如下图:


WX20180626-234918@2x.png

NIO(reactor模型):线程发起IO请求,立即返回;内核在做好IO操作的准备之后,通过调用注册的回调函数通知线程做IO操作,线程开始阻塞,直到操作完成。如下图:


WX20180626-234936@2x.png

AIO(proactor模型):线程发起IO请求,立即返回;内存做好IO操作的准备之后,做IO操作,直到操作完成或者失败,通过调用注册的回调函数通知线程做IO操作完成或者失败。如下图:


WX20180626-234947@2x.png

AIO代码
public class ServerCompletionHandler implements CompletionHandler<AsynchronousSocketChannel, Server> {
@Override
public void completed(AsynchronousSocketChannel result, Server attachment) {
//当有下一个客户端接入的时候 直接调用Server的accept方法,这样反复执行下去,保证多个客户端都可以阻塞
attachment.assc.accept(attachment, this);
read(result);
}

@Override
public void failed(Throwable exc, Server attachment) {
    exc.printStackTrace();
}
private void read(final AsynchronousSocketChannel asc){
    //读取数据
    ByteBuffer buf =
            ByteBuffer.allocate(1024);
    asc.read(buf, buf, new CompletionHandler<Integer, ByteBuffer>() {
        @Override
        public void completed(Integer result, ByteBuffer attachment) {
            //进行读取之后,重新标识位
            attachment.flip();
            //获取读取的字节数
            System.out.println("Server -> " + "收到客户端的数据长度为:" + result);
            //获取读取的数据
            String resultData = new String(attachment.array()).trim();
            System.out.println("Server -> " + "收到客户端的数据信息为:" + resultData);
            String response = "服务器响应, 收到了客户端发来的数据: " + resultData;
            write(asc, response);
        }

        @Override
        public void failed(Throwable exc, ByteBuffer attachment) {
            exc.printStackTrace();
        }
    });
}
private void write(AsynchronousSocketChannel asc,String response){
    try {
        ByteBuffer buf =
                ByteBuffer.allocate(1024);
        buf.put(response.getBytes());
        buf.flip();
        asc.write(buf).get();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
}

public class Server {
//线程在池
private ExecutorService executorService;
//线程组
private AsynchronousChannelGroup threadGroup;
//服务器通道
public AsynchronousServerSocketChannel assc;

public Server(int port) {
    try {
        //创建一个缓冲池
        executorService = Executors.newCachedThreadPool();
        //创建线程组
        threadGroup = AsynchronousChannelGroup.withCachedThreadPool(executorService,1);
        //创建服务器通道
        assc = AsynchronousServerSocketChannel.open(threadGroup);
        //进行绑定
        assc.bind(new InetSocketAddress(port));

        System.out.println("server start , port : " + port);
        //进行堵塞
        assc.accept(this,new ServerCompletionHandler());
        //一直堵塞 不让服务器停止
        Thread.sleep(Integer.MAX_VALUE);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static void main(String[] args){
    Server server = new Server(8765);
}

}

public class Client implements Runnable{
private AsynchronousSocketChannel asc;

public Client(){
    try {
        asc = AsynchronousSocketChannel.open();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
public void connect(){
    asc.connect(new InetSocketAddress("127.0.0.1", 8765));
}

@Override
public void run() {
    while (true){

    }
}
public void write(String request){
    try {
        asc.write(ByteBuffer.wrap(request.getBytes())).get();
        read();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
}
public void read(){
    ByteBuffer buf =
            ByteBuffer.allocate(1024);
    try {
        asc.read(buf).get();
        buf.flip();
        byte[] respByte =
                new byte[buf.remaining()];
        buf.get(respByte);
        try {
            System.out.println(new String(respByte,"utf-8").trim());
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
}

public static void main(String[] args) throws Exception {
    Client c1 = new Client();
    c1.connect();

    Client c2 = new Client();
    c2.connect();

    Client c3 = new Client();
    c3.connect();

    new Thread(c1, "c1").start();
    new Thread(c2, "c2").start();
    new Thread(c3, "c3").start();

    Thread.sleep(1000);

    c1.write("c1 aaa");
    c2.write("c2 bbbb");
    c3.write("c3 ccccc");
}

}

作者:dzzgml
链接:https://juejin.im/post/5b32600ae51d4562aa016647
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

上一篇下一篇

猜你喜欢

热点阅读