6

由于 Guava 的 ListeningExecutorService 是通过包装现有的 ExecutorService 来实现的,因此它通过拦截 execute() 方法来“装饰”任务。这意味着,如果我想在底层 ExecutorService 上使用自定义 PriorityQueue,我的比较器将“看到”装饰任务作为 ListenableFutureTask 对象而不是原始任务。

有没有办法掌握它包装的任务?以便队列的比较器可以使用任务权重来确定排序?

4

1 回答 1

4

我假设你关心submit()而不是execute()?(见我回复的底部。)

使用ListeningExecutorServicefrom MoreExecutors.listeningDecorator(您所指的包装器类型),您就不走运了。listeningDecorator与大多数ExecutorService实现一样,将任何输入包装submitFutureTask. 此问题的正常解决方案是实现AbstractExecutorService并覆盖newTaskFor以返回自定义对象。这也应该在这里工作。您将基本上重新实现listeningDecorator,这是一个相当琐碎的包装器AbstractListeningExecutorService,它本身就是一个相当琐碎的包装器AbstractExecutorService

有两个并发症。(好吧,可能还有更多。我承认我没有测试过我建议的方法。)

  1. AbstractListeningExecutorService不允许您覆盖newTaskFor. (为什么?我可以解释您是否想提交功能请求。)因此,您必须直接扩展AbstractExecutorService,很大程度上复制(短)AbstractListeningExecutorService实现。
  2. newTaskFor必须返回一个ListenableFuture那也是Comparable。a 的明显选择ListenableFutureListenableFutureTask,但是那个类是final,所以你不能创建实例Comparable。解决方案是创建一个ListenableFutureTask并将其包装在一个SimpleForwardingListenableFuture实现Comparable.

为什么我认为您正在处理submit()而不是处理execute()

listeningDecorator(...).execute()不包装输入任务,正如我刚刚写的这个测试所示:

public void testListeningDecorator_noWrapExecuteTask() {
  ExecutorService delegate = mock(ExecutorService.class);
  ListeningExecutorService service = listeningDecorator(delegate);
  Runnable task = new Runnable() {
    @Override
    public void run() {}
  };
  service.execute(task);
  verify(delegate).execute(task);
}
于 2013-09-25T15:39:00.347 回答