• 多线程笔记


    AIO是异步非阻塞io, 也叫 nio2.0.

    直接上代码,

    server:

    public class Server implements Runnable {
    
        public AsynchronousServerSocketChannel assc;
    
        private CountDownLatch latch;
    
        public Server(int port) {
            try {
                assc = AsynchronousServerSocketChannel.open();
                assc.bind(new InetSocketAddress(port));
                System.out.println("服务器启动 : " + port);
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void run() {
            latch = new CountDownLatch(1);
    
            assc.accept(this, new ServerCompletionHandler());
    
            try {
                latch.await();
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    
        public static void main(String[] args) {
            new Thread(new Server(1234)).start();
        }
    }

    ServerCompletionHandler 是一个回调类, 里面封装了连接成功后的回调方法:
    public class ServerCompletionHandler   implements CompletionHandler<AsynchronousSocketChannel, Server> {
        @Override
        public void completed(AsynchronousSocketChannel asc, Server attachment) {
            //当有下一个客户端接入的时候 直接调用Server的accept方法,
            // 这样反复执行下去,保证多个客户端都可以阻塞
            attachment.assc.accept(attachment, this);
            read(asc);
        }
    
        private void read(final AsynchronousSocketChannel asc) {
            //读取数据
            ByteBuffer buf = ByteBuffer.allocate(1024);
            asc.read(buf, buf, new CompletionHandler<Integer, ByteBuffer>() {
                @Override
                public void completed(Integer resultSize, ByteBuffer attachment) {
                    //进行读取之后,重置标识位
                    attachment.flip();
                    //获得读取的字节数
                    System.out.println("Server -> " + "收到客户端的数据长度为:" + resultSize);
                    //获取读取的数据
                    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();
            }
        }
    
        @Override
        public void failed(Throwable exc, Server attachment) {
            exc.printStackTrace();
        }
    }

    客户端:

    public class ClientA implements Runnable{
    
        private AsynchronousSocketChannel asc ;
    
        private CountDownLatch latch = new CountDownLatch(1);
    
        public ClientA(){
            try {
                asc = AsynchronousSocketChannel.open();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public void connect(){
            //与服务器建立连接
            asc.connect(new InetSocketAddress("127.0.0.1", 1234));
        }
    
        public void read(){
            ByteBuffer buf = ByteBuffer.allocate(1024);
            try {
                asc.read(buf).get();
                buf.flip();
                byte[] respByte = new byte[buf.remaining()];
                buf.get(respByte);
                System.out.println(new String(respByte,"utf-8").trim());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
    
        public void write(String request){
            try {
                asc.write(ByteBuffer.wrap(request.getBytes())).get();
                read();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void run() {
            try {
                //让线程不退出
                latch.await();
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) throws Exception {
            ClientA c1 = new ClientA();
            c1.connect();
    
            ClientA c2 = new ClientA();
            c2.connect();
    
            ClientA c3 = new ClientA();
            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");
        }
    }

    结果:

    client: 

    server: 

     各种io比较表:

      同步阻塞(BIO) 伪异步IO 同步非阻塞(NIO) 异步非阻塞(AIO)
    客户端个数: I/O线程 1:1

    M:N

    (M可大于N)

    M:1 

    (1个I/O线程处理

    多个客户端连接)

    M:0

    (不需要启动额外的I/O线程

    ,被动回调)

    I/O类型(阻塞) 阻塞I/O 阻塞I/O 非阻塞I/O 非阻塞I/O
    I/O类型(同步) 同步I/O 同步I/O

    同步I/O

    (I/O多路复用)

    异步I/O
    API使用难度 简单 简单 非常复杂 复杂
    调试难度 简单 简单 复杂 复杂
    可靠性 非常差
    吞吐量
    参考:
      Netty权威指南
  • 相关阅读:
    41:和为S的两个数
    40:数组中只出现一次的数字
    39-2:平衡二叉树
    39:二叉树的深度
    38:数字在排序数组中出现的次数
    37:两个链表的第一个公共结点
    36:数组中的逆序对
    35:第一个只出现一次的字符
    34:丑数
    33:把数组排成最小的数
  • 原文地址:https://www.cnblogs.com/elvinle/p/12389940.html
Copyright © 2020-2023  润新知