有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

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

有什么建议吗


共 (2) 个答案

  1. # 1 楼答案

    我将创建ThreadPoolExecutor的子类

    在设置ThreadPoolExecutor时,您希望将corePoolSizemaximumPoolSize设置为Runtime.getRuntime().availableProcessors()(查看Executors.newFixedThreadPool()以了解其工作原理)

    接下来,您要确保您的Queue也实现了DequeLinkedBlockingDeque就是一个例子,但是你应该四处看看哪一个最适合你。一个Deque允许您获得堆栈式的后进先出行为,这正是您想要的

    因为所有(submit()invokeAll())都是通过execute()进行的,所以您需要重写此方法。基本上按照您上面描述的操作:

    检查是否所有线程都在运行。如果不是,只需在可用线程上启动新的runnable即可。如果所有线程都已经在运行,那么您需要找到运行最早的runnable的线程,停止runnable,将runnable重新排入某个位置(可能在开始时?),然后开始新的runnable

  2. # 2 楼答案

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

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

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

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