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)无法响应,则应该断开连接。
网友评论