嘿,所以我为ExecutorService的java文档选择了这个例子。我想确认这段代码的流程,Executors.newFixedThreadPool 将创建一个线程池(我猜(。因此,serversocket 将等待连接,一旦获得连接,它就会启动一个线程,所以现在 poolsize 减少了 1。线程完成执行后,poolsize 将再次增加 1,不是吗?线程会放弃它使用的资源吗?
class NetworkService implements Runnable {
private final ServerSocket serverSocket;
private final ExecutorService pool;
public NetworkService(int port, int poolSize)
throws IOException {
serverSocket = new ServerSocket(port);
pool = Executors.newFixedThreadPool(poolSize);
}
public void run() { // run the service
try {
for (;;) {
pool.execute(new Handler(serverSocket.accept()));
}
} catch (IOException ex) {
pool.shutdown();
}
}
}
class Handler implements Runnable {
private final Socket socket;
Handler(Socket socket) { this.socket = socket; }
public void run() {
// read and service request on socket
}
}
线程完成执行后,poolsize 将再次增加 1,不是吗?
是的。 线程将获取并运行下一个Handler
。
不是线程会放弃它使用的资源吗?
立即,不是。 Handler
run()
方法完成后,Handler
将超出范围。 但是,您必须等待垃圾回收器运行,然后才能释放Handler
实例。 这将反过来释放Socket
,然后成为垃圾回收本身的候选者。
如果您希望尽快发布Socket
(我认为这是问题所在(,则应在run()
方法结束时完成。 您可以在finally
块中调用socket.close()
(也可以将socket
设置为null
(。 建议使用类似以下内容的内容:
class Handler implements Runnable {
...
public void run() {
try {
// read and service request on socket
} finally {
// make sure we close the socket when the handler is finishing
socket.close();
}
}
}
所做的只是执行你的Runnable
。
因此,如果您需要在完成任务后进行任何清理,则应从Runnable
进行。池只是一个Producer
- Consumer
模式实现,负责管理线程的生命周期。
线程执行您在队列中传递的任务,因此在您的情况下,socket
不会在线程之间重用。它的范围在Runnable
由于它是一个 fixedThreadPool,是的,每次将任务提交到池时,池大小都会减小,一旦线程运行完提交的可运行(或可调用(,池大小就会增加。向固定线程池提交更多数量的可运行项将阻塞,直到池中的任何线程完成运行其之前提交的任务。