嘿所以我为ExecutorService的java文档选择了这个例子。我想确认这段代码的流程,Executors.newFixedThreadPool会创建一个线程池(我猜)。所以serversocket会等待一个连接,一旦它获得一个,它就会启动一个线程,所以现在poolize减少了1.一旦线程完成执行,poolize将再次递增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
}
}
答案 0 :(得分:1)
一旦线程完成执行,poolize将再次递增1,不是吗?
是。线程将采取并运行下一个Handler
。
线程会放弃它使用的资源吗?
不是立即,不是。完成Handler
run()
方法后,Handler
将超出范围。但是,您必须等待垃圾收集器在Handler
实例发布之前运行。这将依次释放Socket
,然后它就成为垃圾收集的候选者。
如果您希望尽快释放Socket
(我认为这是问题),那么应该在run()
方法结束时完成。您可以在socket.close()
块中调用socket
(并可能将null
设置为finally
)。建议使用以下内容:
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();
}
}
}
答案 1 :(得分:0)
所有线程都执行你的 Runnable
因此,如果您需要在完成任务之后进行任何清理,应该从Runnable
执行此操作。该池只是Producer
- Consumer
模式实现,负责管理线程的生命周期。
线程执行您在队列中传递的任务,因此在您的情况下,socket
不会在线程之间重用。它的范围在Runnable
答案 2 :(得分:0)
由于它是fixedThreadPool,是的,每次将任务提交到池中时,池大小都会减少。一旦线程完成运行提交的runnable(或可调用),就会增加。 向固定线程池提交更多可运行数将被阻塞,直到池中的任何线程完成运行其先前提交的任务为止。