如果ExecutorService的队列已满,会发生什么

Tru*_* Ha 6 java concurrency runtime-error out-of-memory

我有一个高达TB的大文件,我的任务是逐行处理.每一行应该花费5秒才能完成.为了提高性能,我将进程分配给这样的固定线程池

ExecutorService executor = Executors.newFixedThreadPool(5);     

while ((line = br.readLine()) != null) {
  Runnable worker = new WorkerThread(line);
  executor.execute(worker); 
}
Run Code Online (Sandbox Code Playgroud)

我的问题是如果我通过执行如此多的任务来压倒执行程序的队列会发生什么.它扔了StackOverflow吗?

Joh*_*int 5

如果处理速度不如预期,则会抛出OOM错误(gc开销)。StackOverflow由于堆栈变化不大,您无法获得A。

@StinePike提出了一个很好的问题。 RejectedExecutionException如果没有更多线程来处理队列外的项目并且队列已满,则会发生这种情况。在这种情况下,的默认实现Executors.newFixedThreadPool(5);将使用unbounded LinkedBlockingQueue。您唯一的限制是记忆。

  • 它会抛出RejectedExecutionException吗? (2认同)
  • 仅当队列为固定大小时才使用@StinePike,默认情况下,该IIRC是无限制队列。 (2认同)

Tha*_*Mai 5

这可能是一个主题,但是这个问题的一个选项是使用固定长度的阻塞队列并使用ThreadPoolExecutor.CallerRunPolicy().这样,如果消费者不够快(因此队列正在填满),那么将使用调用者线程(生产者)来运行任务本身.我们可以像下面这样初始化一个Executor:

executorService = new ThreadPoolExecutor(DEFAULT_THREAD_COUNT,
        DEFAULT_THREAD_COUNT, 2, TimeUnit.MINUTES,
        new ArrayBlockingQueue<Runnable>(DEFAULT_QUEUE_LENGTH),
        new ThreadPoolExecutor.CallerRunsPolicy());
Run Code Online (Sandbox Code Playgroud)

来自API: "被拒绝任务的处理程序,它直接在execute方法的调用线程中运行被拒绝的任务,除非执行程序已被关闭,在这种情况下任务被丢弃."