Java是否具有可索引的多队列线程池?

时间:2013-07-31 14:15:37

标签: java multithreading queue threadpool

是否存在以下Java类:

  1. 可执行任务可以通过id添加,其中具有相同id的所有任务都保证永远不会同时运行
  2. 线程数可以限制为固定数量
  3. 地图的天真解决方案很容易解决(1),但管理难度很大(2)。类似地,我所知道的所有线程池类都将从单个队列中提取,这意味着(1)不能得到保证。

    欢迎涉及外部图书馆的解决方案。

4 个答案:

答案 0 :(得分:4)

对于每个id,您需要一个SerialExecutor,在java.util.concurrent.Executor的文档中描述。所有串行执行程序都将工作委托给具有给定corePoolSize的ThreadPoolExecutor

可以在my code samples找到最佳版本的SerialExecutor。

答案 1 :(得分:3)

如果您没有找到开箱即用的东西,那么推出自己的东西应该不难。你可以做的一件事是将每个任务包装在一个简单的类中,该类读取每个id唯一的队列,例如:

public static class SerialCaller<T> implements Callable<T> {
    private final BlockingQueue<Caller<T>> delegates;

    public SerialCaller(BLockingQueue<Caller<T>> delegates) {
        this.delegates = delegates;
    }

    public T call() throws Exception {
        return delegates.take().call();
    }
}

将ID的映射维护到队列以提交任务应该很容易。这满足条件(1),然后你可以找到条件(2)的简单解决方案,例如Executors. newFixedThreadPool

答案 2 :(得分:2)

我认为最简单的解决方案是为每个索引创建一个单独的队列,为每个队列创建一个单独的执行器(带一个线程)。

使用更复杂的解决方案,唯一可以实现的就是使用更少的线程,但如果索引的数量很少且有限,则可能不值得付出努力。

答案 3 :(得分:1)

是的,现在有这样一个库:https://github.com/jano7/executor

int maxTasks = 10;
ExecutorService underlyingExecutor = Executors.newFixedThreadPool(maxTasks);
KeySequentialBoundedExecutor executor = new KeySequentialBoundedExecutor(maxTasks, underlyingExecutor);

Runnable task = new Runnable() {
    @Override
    public void run() {
        // do something
    }
};

executor.execute(new KeyRunnable<>("ID-1", task)); // execute the task by the underlying executor
executor.execute(new KeyRunnable<>("ID-2", task)); // execution is not blocked by the task for ID-1
executor.execute(new KeyRunnable<>("ID-1", task)); // execution starts when the previous task for ID-1 completes