JAVA 线程池与NIO Socket链接

2018-01-08  本文已影响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)无法响应,则应该断开连接。

上一篇下一篇

猜你喜欢

热点阅读