1

嘿,所以我为 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
 }
}
4

3 回答 3

1

一旦线程完成执行,池大小将再次增加 1,不是吗?

是的。线程将继续运行下一个Handler

线程会放弃它使用的资源吗?

不是马上,不是。一旦Handler run()方法完成,Handler就会超出范围。但是,您必须等待垃圾收集器运行才能Handler释放实例。这将反过来释放Socket,然后成为垃圾收集本身的候选者。

如果您希望您Socket尽快被释放(我认为这是问题所在),那么应该在run()方法结束时完成。您可以在一个块中调用socket.close()(并且可能设置socket为)。建议使用以下内容:nullfinally

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();
       }
    }
}
于 2012-08-29T18:41:39.240 回答
0

由于它是一个固定线程池,是的,每次将任务提交到池中时池大小都会减小,一旦线程完成运行提交的可运行(或可调用),池大小就会增加。向固定线程池提交更多数量的可运行程序将阻塞,直到池中的任何线程完成运行其先前提交的任务。

于 2012-08-29T18:43:45.750 回答
0

所有线程所做的就是执行 Runnable的 s.
因此,如果您需要在完成任务后进行任何清理,应该从Runnable. 池只是一种模式实现ProducerConsumer负责管理线程的生命周期。
线程执行您在队列中传递的任务,因此在您的情况下,socket线程之间不会重用。它的范围在Runnable

于 2012-08-29T18:40:25.213 回答