美文网首页
JAVA 线程池与NIO Socket链接

JAVA 线程池与NIO Socket链接

作者: 爱蛇 | 来源:发表于2018-01-08 22:14 被阅读0次

    JAVA线程池

    核心类 ThreadPoolExecutor,实例化需要指定一个队列。
    跟Tomcat一样,有一个固定数量线程的线程池并且有一个请求队列,当
    处理请求的线程已经用完时(所有线程处于工作状态时),所有请求都会放在队列中,而ThreadPoolExecutor也是一个道理。

    //实例化一个只能存放3个请求的线程
     BlockingQueue queue = new ArrayBlockingQueue(3);
    //实例化一个最多2条用于处理请求线程,当线程池用完其他请求会存放在queue 中
     ExecutorService executor = new ThreadPoolExecutor(1, 2, 1, TimeUnit.DAYS, queue);
    
    //注意ThreadPoolExecutor实例化所需要队列接口为BlockingQueue 
    //表示同一时间只会有一个请求放到队列中
    

    定义请求处理器(即请求)

    class Handler implements Runnable {
            @Override
            public void run() {
                log("处理请求代码");
            }
        }
    

    执行请求处理

    Handler  handler = new Handler();
    //如果当前线程池所有线程都用完时,该handler不会被执行,直到有空闲的线程时。
    executor.execute(handler);
    

    NIO Socket服务端

    那么问题来了,配合NIO Socket循环接受连接
    就会有可能导致
    连接长时间处于连接而同时又是待处理状态:

    while (true) {
     log("Start accept");
     SocketChannel socketChannel = serverSocketChannel.accept();
                if (socketChannel == null) {
                    log("new Connection is null");
                } else {
                    log("new Connection,ip:%s", socketChannel.getRemoteAddress());
                    OnConnection connection = new OnConnection(socketChannel);
                    //当线程用完时,连接会被放到队列queue中,直到线程池中有空闲的线程
                    //如果这些客户端连接一直处于等待而不断开连接状态,那么queue会一直被堆满,
                    //并且由于连接没有释放导致内存一直积压
                    executor.execute(connection);
                }
    }
    

    所以一个合理的C/S交互是应该设计超时策略,当超时时间内对方(S或C)无法响应,则应该断开连接。

    相关文章

      网友评论

          本文标题:JAVA 线程池与NIO Socket链接

          本文链接:https://www.haomeiwen.com/subject/qdsinxtx.html