0

我有一个ExecutorService(或 atm 的子类ThreadPoolExecutorService),我将任务传递给submit(Runnable r).

有时,相同的任务会在它仍在运行时(重新)提交,然后我希望第二个提交等待第一个完成。即排队。如何做到这一点是一种更可取的方式?只有当提交的任务已经在运行时才应该排队,否则应该直接执行。

返回Future<>的 s 有时会用于取消任务。

像这样的东西;

    Runnable r = new LengthyRunnable();

    Future<?> f1 = submit(r); //should start to run
    Future<?> f2 = submit(r); //should be queued and wait for f1
    Future<?> f3 = submit(r); //in case f1 hasnt finished, and f2 is queued, should remove f2 from the queue and take it's place

我已经将 ThreadPoolExecutorService 子类化,并且我使用 beforeExecute 和 afterExecute 来跟踪任务,但这变得越来越困难......我应该使用除 a 之外的其他东西ThreadPoolExecutorService吗?

4

2 回答 2

0

我会做LengthyRunnable一个重复的任务(有一个合适的池间隔)来检查它是否需要再次运行。这样你就可以确定它不会运行多次。

于 2013-01-14T18:50:22.143 回答
0

当 f3 已入队且 f2 尚未启动时,您希望删除已入队的 f2 任务。但是 ExecutorService 不会公开对队列的访问,因为底层实现可能甚至不是异步的。ThreadPoolExecutor 有一个底层队列,但实际上并没有公开它:)

如果您不想像某人建议的那样简单地进行可调度/循环任务,那么您可以考虑以下内容。

创建一个 WorkPerformer Runnable。将某种BlockingQueue 传递给它,即LinkedBlockingQueue。该队列将用于将您需要执行的某种 LongyTask 排入队列。

在调用代码中,您将创建一个可以窥视队列的同步块 - 如果 f2 在那里并且 f1 仍在运行(WorkPerformer 将具有某种同步标志),您将使 f2 出队并将 f3 入队。

如果不知道您背后的意图是什么,就很难提出更多/更好的建议。

于 2013-01-14T21:41:04.763 回答