Java: ExecutorService that blocks on submission after a certain queue size

前端 未结 7 1379
Happy的楠姐
Happy的楠姐 2020-11-30 17:38

I am trying to code a solution in which a single thread produces I/O-intensive tasks that can be performed in parallel. Each task have significant in-memory data. So I want

7条回答
  •  -上瘾入骨i
    2020-11-30 17:58

    The currently accepted answer has a potentially significant problem - it changes the behavior of ThreadPoolExecutor.execute such that if you have a corePoolSize < maxPoolSize, the ThreadPoolExecutor logic will never add additional workers beyond the core.

    From ThreadPoolExecutor.execute(Runnable):

        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        else if (!addWorker(command, false))
            reject(command);
    

    Specifically, that last 'else' block willl never be hit.

    A better alternative is to do something similar to what OP is already doing - use a RejectedExecutionHandler to do the same put logic:

    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        try {
            if (!executor.isShutdown()) {
                executor.getQueue().put(r);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RejectedExecutionException("Executor was interrupted while the task was waiting to put on work queue", e);
        }
    }
    

    There are some things to watch out for with this approach, as pointed out in the comments (referring to this answer):

    1. If corePoolSize==0, then there is a race condition where all threads in the pool may die before the task is visible
    2. Using an implementation that wraps the queue tasks (not applicable to ThreadPoolExecutor) will result in issues unless the handler also wraps it the same way.

    Keeping those gotchas in mind, this solution will work for most typical ThreadPoolExecutors, and will properly handle the case where corePoolSize < maxPoolSize.

提交回复
热议问题