Java:一个多线程Executor内的单线程子Executor

4

我希望能够以串行方式运行一些任务。这种情况的典型解决方案是创建一个

Executor executor = Executors.newSingleThreadedExecutor();

并在此上运行任务。

不过,我已经有一个多线程的线程池了。

是否有一种简单的方法可以派生出一个子执行器,它的行为类似于单线程执行器(即:每次只运行一个任务),但是使用另一个(可能不是单线程的)执行器作为“后端”,而不是创建一个全新的操作系统线程?

有几种用例说明了我们为什么要这样做:

  • 应用程序可能已经有一个线程池,例如用于后台任务,并设置了优先级等,我们希望重用该线程池。
  • 同样地,我们可能会传入一个不仅仅是普通线程池的执行器(例如推迟执行以供稍后执行、测量执行时间等)。
    • 其中的一个子集是传递MoreExecutors.directExecutor()进行测试(以便例如Futures立即解决)。

编辑:添加了上述示例


2
你能把你想要在单个线程中运行的任务代码放进去吗?我认为在单个线程中运行任务取决于任务本身。如果你不想在另一个线程中执行任务,它将仅在同一线程中运行。 - Vijendra Kumar Kulhade
我同意Vijendra的观点 - 你的问题很有趣,但是为了给出更有帮助的反馈,一些代码可能会对我们有所帮助。 - GhostCat
2个回答

2

这样的零线程执行器被称为SerialExecutor,并在Java文档中描述为java.util.concurrent.Executor。然而,它有一个小缺点:对于每个提交的Runnable,它都会创建一个包装对象。我自己的实现不会创建额外的对象。


很酷,谢谢!不过有点惊讶他们会把一个有用的类放在Java文档中,而不是实际的代码...我想知道它被复制了多少次。 - Latanius

0

我的建议是:不要这么做。

从实际角度来看,这似乎没有太多意义:你想引入一个更复杂的解决方案,去解决一个并不是真正问题的问题。

你可以看到:当那个“其他”的多线程服务处于空闲状态时……为什么你要使用它?如果你想节约操作系统线程资源,为什么要使用那个看起来无所事事的多线程服务呢?

但是,如果它没有空闲时间 - 你认为你如何以一致的方式从那个“单线程”服务中引入任务呢?

是的,线程不是很便宜;但是当你确实需要节省单个线程来解决一个问题时……回到上一段,并再次问问自己:那个空闲的多线程服务呢?

也许有一种技术方式来实现你的想法;但说实话,我的答案是 - 坚持你已经拥有的:

Executor executor = Executors.newSingleThreadedExecutor();

并且补充另一个答案/评论:是的,演员模型可能会有所帮助;但混淆概念很少是一个好主意。如果Actor方法很好地适合您的整体模型(也许有很好的方法可以更改代码的更多部分以利用它)-那就好。但如果不是这样,请小心添加额外的概念复杂性来解决问题...正如前面所说的,这可能根本不是一个真正的问题。

1
主题发起者想要的实际上是一个Actor,它接受类型为Runnable的消息,并通过调用message.run()来处理它们。Actor的概念并不复杂,足够直观,并且在过去40年中已经成功开发。请参见https://github.com/rfqu/CodeSamples/tree/master/src/simpleactor的详细信息。 - Alexei Kaigorodov
我喜欢你简洁的回答,因此给了个赞;但我思考了一段时间后,决定也保留我的答案。一切都取决于问题的“严重程度”。我们做事情不是因为我们能够做到,而是因为它们是有意义的,并且能够改进一些值得改进的东西。如果一个解决方案今天使用两个池可行,那么通过大规模的重新工作来使用一个池,你获得了什么呢?(也许很多,但这确实非常依赖于他正在做什么,以及发生在哪个规模上)。 - GhostCat
谢谢你的回答!我同意在大多数情况下这可能是个好主意,而且操作系统线程毕竟并不昂贵。然而,在一些更奇怪的情况下,它可能会很有用;请参见我上面添加的例子。 - Latanius

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接