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

时间:2010-07-22 09:33:38

标签: java multithreading scheduling

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

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

有什么建议吗?

2 个答案:

答案 0 :(得分:4)

我会创建一个ThreadPoolExecutor的子类。

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

接下来,您要确保Queue也实施DequeLinkedBlockingDeque就是一个例子,但你应该四处寻找,看看哪一款最适合你。 Deque允许您像LIFO行为一样获得堆栈,这正是您想要的。

由于所有内容(submit()invokeAll())都会通过execute()进行汇总,因此您需要覆盖此方法。基本上做你上面描述的:

检查所有线程是否都在运行。如果不是简单地在可用线程上启动新的runnable。如果所有线程都已经运行,那么你需要找到运行最早runnable的线程,停止runnable,在某处重新排队runnable(可能在开头?),然后启动新的runnable。

答案 1 :(得分:1)

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

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

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

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