Java线程池 - 线程正在更新?

时间:2013-01-19 14:00:55

标签: java multithreading

我的Java.NIO套接字服务器中有一个线程池。 我有时会收到Connection reset by peerBroken Pipe等运行时错误。

我的问题是:抛出异常时线程被杀死了吗?如果是 - 是在线程池中创建的新线程代替被杀死的线程??

这是我的ThreadManager:

import java.nio.channels.SocketChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class ThreadsManager {

    private ExecutorService threadPool = null;
    private LiveConnectionsManager liveConnectionsManager;
    private int threadPoolSize = 35; //number of tasks thread

    public ThreadsManager(LiveConnectionsManager liveConnectionsManager) {
        this.liveConnectionsManager = liveConnectionsManager;
        threadPool = Executors.newFixedThreadPool(threadPoolSize);
        ServerActions.threadPool = threadPool;
    }

    public void processNewMessage(SocketChannel socketChannel, Client client)
    {
        threadPool.execute(new MessagesProcessor(socketChannel, client, liveConnectionsManager));
    }

    public void closeConnection(SocketChannel socketChannel, Client client) {
        threadPool.execute(new LogoutClient(socketChannel, client, null));
    }   
}

3 个答案:

答案 0 :(得分:11)

使用 ExecutorService 创建线程池时。

所以 ExecutorService.newFixedThreadPool(..)确保如果线程数被任何异常/错误杀死并且有足够的任务等待线。 java doc下面的文字清楚地说明了这一点:

直接来自java doc:newFixedThreadPool

创建一个线程池,该线程池重用在共享的无界队列中运行的固定数量的线程。 在任何时候,最多nThreads线程都将处于活动状态处理任务。如果在所有线程都处于活动状态时提交了其他任务,则它们将在队列中等待,直到线程可用。如果任何线程由于在关闭之前执行期间的故障而终止,则在需要执行后续任务时将使用新的线程。池中的线程将一直存在,直到明确关闭。

http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool(int

答案 1 :(得分:4)

ThreadPoolExecutor根据您选择的设置(在构造函数中传递或通过您使用的辅助方法)管理线程数。它的工作方式与ThreadPoolExecutor javadoc中描述的一样。

从构造函数(下面列出)中,最有趣的参数是corePoolSizemaximumPoolSizecorePoolSize是保持活动状态的最低线程数。如果一个线程被杀死并且由于这个线程数下降到这个数字以下,新线程将被启动[1](在某些时候)。

maximumPoolSize是池中线程的最大数量。如果这高于corePoolSize,则您的池可能最终会有更多线程,然后您已在corePoolSize参数中指定。如果其中一个线程此时死亡并且活动线程数不会低于corePoolSize个数,则不会创建新线程。

您通过 Executors 帮助程序类创建的固定线程池具有corePoolSize == maximumPoolSize,因此服务确实会确保相同数量的线程始终可用[1](当需要)。

[1] 一个重要的通知是线程的创建是“按需”发生的 - 也就是说如果一个线程死了并且队列中没有任务,那么就不会创建线程直到它不需要(通过在上面已经可用的线程上排队)。

/**
 * Creates a new <tt>ThreadPoolExecutor</tt>( ... cut irelevant part ... )
 *
 * @param corePoolSize the number of threads to keep in the
 * pool, even if they are idle.
 * @param maximumPoolSize the maximum number of threads to allow in the
 * pool.
 * ( ... cut irelevant part ... )
 */
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), defaultHandler);
}

[编辑] - 忘记了另一个问题。 实际上,Exceptions会杀死Worker线程 - 你需要在内部处理错误。 有关详细信息,请检查java.util.concurrent.ThreadPoolExecutor.Worker类。它的runTask方法值得检查。

答案 2 :(得分:0)

  

我的问题是:在捕获错误时线程是否会被杀死?

     

如果确实如此 - 线程池用新线程填充它在池中的位置?

Executors.newFixedThreadPool创建的执行程序将在池中的某个线程死亡时创建一个新线程,因此问题第二部分的答案是肯定的。至于第一部分,如果没有看到MessagesProcessorLogoutClient的代码就不可能说,但考虑到任何死线都将被替换,它并不重要。如果MessagesProcessorLogoutClient在内部捕获并记录异常

public void run() {
  try {
    // do stuff
  } catch(Exception e) {
    e.printStackTrace();
  }
}

然后异常不会传播出run方法,因此不会终止正在运行任务的线程,因此它将能够返回池中。但是如果它们没有捕获异常,并且它们允许RuntimeException被抛出run方法,则线程将会死亡(并被新的替换)。