具有可抢占线程队列的java执行器

发布于 2024-09-11 02:44:08 字数 186 浏览 6 评论 0原文

我正在寻找一个java线程池,它不会同时运行比系统中核心数量更多的线程。该服务通常由 ThreadPoolExecutor 使用 BlockingQueue 提供。

但是,如果计划执行一个新线程,我希望新线程抢占已运行的线程之一,并将抢占的线程(处于挂起状态)添加到任务队列中,这样就可以新线程完成后立即恢复。

有什么建议吗?

I'm looking for a java thread-pool, that won't run more threads simultaneously than there are cores in the system. This service is normally provided by a ThreadPoolExecutor using a BlockingQueue.

However, if a new thread is scheduled to execute, I want the new thread to pre-empt one of the already running threads, and add the the pre-empted thread (in a suspended state) to a task queue, so it can be resumed as soon as the new thread is finished.

Any suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

屋顶上的小猫咪 2024-09-18 02:44:08

我将创建 ThreadPoolExecutor 的子类。

当您设置 ThreadPoolExecutor 时,您需要将 corePoolSizemaximumPoolSize 设置为 Runtime.getRuntime().availableProcessors() (查看 >Executors.newFixedThreadPool() 以了解其工作原理)。

接下来,您要确保您的 Queue 也实现 DequeLinkedBlockingDeque 是一个示例,但您应该货比三家,看看哪一个最适合您。 Deque 允许您获得类似于 LIFO 行为的堆栈,这正是您想要的。

由于所有内容(submit()invokeAll())都通过 execute() 传递,因此您需要重写此方法。基本上执行上面描述的操作:

检查所有线程是否正在运行。如果不是,只需在可用线程上启动新的可运行程序即可。如果所有线程都已经在运行,那么您需要找到运行最旧的可运行的线程,停止可运行的线程,将可运行的线程重新排队到某处(也许在开始处?),然后启动新的可运行的线程。

I would make a subclass of ThreadPoolExecutor.

When you setup your ThreadPoolExecutor you want to set the corePoolSize and the maximumPoolSize to Runtime.getRuntime().availableProcessors() (Look at Executors.newFixedThreadPool() to see why this works).

Next you want to make sure that your Queue also implements Deque. LinkedBlockingDeque is an example but you should shop around to see which one will work best for you. A Deque allows you to get stack like LIFO behavior which is exactly what you want.

Since everything (submit(), invokeAll()) funnels through execute() you will want to override this method. Basically do what you described above:

Check if all threads are running. If not simply start the new runnable on an available thread. If all the threads are already running then you need to find the one running the oldest runnable, stop the runnable, re-queue the runnable somewhere (maybe at the beginning?), and then start your new runnable.

樱花坊 2024-09-18 02:44:08

ThreadPoolExecutor 的想法是避免与创建和销毁线程相关的所有昂贵操作。如果您绝对坚持抢占正在运行的任务,那么您将无法从默认 API 中获得这一点。

如果您愿意允许正在运行的任务完成,而只抢占尚未开始执行的任务,那么您可以使用 BlockingQueue 实现,它的工作方式类似于堆栈 (LIFO)。

您还可以通过使用具有不同线程优先级的不同执行器来让任务“抢占”其他任务。本质上,如果操作系统支持时间片,那么优先级较高的执行程序将获得时间片。

否则,您需要一个管理执行的自定义实现。您可以使用 SynchronousQueue 并让 P 个工作线程在其上等待。如果客户端调用execute并且SynchronousQueue.offer失败,那么您必须创建一个特殊的工作线程,它捕获其他线程之一并在执行之前将它们标记为停止,并在执行后再次将它们标记为恢复。

The idea of a ThreadPoolExecutor is to avoid all of the expensive actions related to creating and destroying a thread. If you absolutely insist on preempting the running tasks, then you won't get that from the default API.

If you are willing to allow the running tasks to complete and instead only preempt the tasks which have not begun execution, then you can use a BlockingQueue implementation which works like a Stack (LIFO).

You can also have tasks 'preempt' other tasks by using different executors with different thread priorities. Essentially, if the OS supports time-slicing, then the higher priority executor gets the time-slice.

Otherwise, you need a custom implementation which manages execution. You could use a SynchronousQueue and have P worker threads waiting on it. If a client calls execute and SynchronousQueue.offer fails, then you would have to create a special worker Thread which grabs one of the other Threads and flags them to halt before executing and again flags them to resume after executing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文