• Netty权威指南之伪异步I/O编程


    为了解决同步阻塞I/O一个链路需要一个线程处理问题,对BIO模型做了优化——后端通过一个线程池处理多个客户端的请求接入,设置线程最大值,防止线程并发接入导致的线程耗尽。

    当有新的客户端接入时,将客户端Socket封装成一个Task(该任务实现java.lang.Runnable接口)投递到后端的线程池中进行处理,JDK的线程池维护一个消息队列和N个活跃线程,对消息队列中的任务进行处理。由于线程池可以设置消息队列的大小和最大线程数,因此资源占用是可控的,无论多少客户端并发访问都不会导致资源耗尽和宕机。

    伪异步I/O通信框架采用了线程池实现,避免了每次请求创建一个独立的线程造成的资源耗尽问题,底层通信依然采用BIO同步阻塞模型,无法从根本上解决问题。当对方发送请求或者应答消息比较缓慢(如数据大),或者网路传输较慢时(网速差)读取输入流一方的通信线程将被长时间阻塞,阻塞期间,其他接入消息只能在消息队列中排队。阻塞结束情况:1)有数据可读,2)可用数据已经读取完毕,3)发生空指针或IO异常

    package com.hjp.netty.pseudoasynio;
    
    
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    public class TimeServerHandlerExecutePool {
    
        private ExecutorService executor;
    
        public TimeServerHandlerExecutePool(int maxPoolSize, int queueSize) {
            executor = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), maxPoolSize, 120L, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(queueSize));
        }
    
        public void execute(Runnable task) {
            executor.execute(task);
        }
    
    }
    线程池处理类
    package com.hjp.netty.pseudoasynio;
    
    import sun.awt.windows.ThemeReader;
    
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TimeServer {
    
        public static void main(String[] args) throws IOException {
            int port = 8080;
            if (args != null && args.length > 0) {
                try {
                    port = Integer.valueOf(port);
                } catch (NumberFormatException e) {
                    e.printStackTrace();
                }
            }
            ServerSocket server = null;
            try {
                server = new ServerSocket(port);
                System.out.println("The time server is start in port : " + port);
                Socket socket = null;
                TimeServerHandlerExecutePool singleExecutor = new TimeServerHandlerExecutePool(50, 10000);
                while (true) {
                    socket = server.accept();
                    singleExecutor.execute(new TimeServerHandler(socket));
                }
            } finally {
                if (server != null) {
                    System.out.println("The time server close");
                    server.close();
                    server = null;
                }
            }
        }
    
    }
    TimeServer
    package com.hjp.netty.pseudoasynio;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.Socket;
    import java.util.Date;
    
    public class TimeServerHandler implements Runnable {
    
        private Socket socket;
    
        public TimeServerHandler(Socket socket) {
            this.socket = socket;
        }
    
        @Override
        public void run() {
            BufferedReader in = null;
            PrintWriter out = null;
            try {
                in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
                out = new PrintWriter(this.socket.getOutputStream(), true);
                String currentTime = null;
                String body = null;
                while (true) {
                    body = in.readLine();
                    if (body == null) {
                        break;
                    }
                    System.out.println("The time server receive order : " + body);
                    currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new Date(System.currentTimeMillis()).toString() : "BAD ORDER";
                    out.println(currentTime);
                }
            } catch (Exception e) {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }
                if (out != null) {
                    out.close();
                    out = null;
                }
                if (this.socket != null) {
                    try {
                        this.socket.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                    this.socket = null;
                }
            }
        }
    }
    TimeServerHandler

    客户端代码和BIO客户端代码一样

  • 相关阅读:
    RocketMq(一、双master模式集群搭建)
    activeMQ(二、与springboot集成)
    activeMQ(一、基础练习)
    oracle分区【转载】
    oracle索引
    实习 | 第一天
    再学ajax--第二天 | 基于php+mysql+ajax的表单注册、登录、注销
    再学ajax--第一天
    ECMAScript6入门学习--第一天
    关于px、pt、em、rem四个单位的解释
  • 原文地址:https://www.cnblogs.com/hujiapeng/p/6368731.html
Copyright © 2020-2023  润新知