由于 Guava 的 ListeningExecutorService 是通过包装现有的 ExecutorService 来实现的,因此它通过拦截 execute() 方法来“装饰”任务。这意味着,如果我想在底层 ExecutorService 上使用自定义 PriorityQueue,我的比较器将“看到”装饰任务作为 ListenableFutureTask 对象而不是原始任务。
有没有办法掌握它包装的任务?以便队列的比较器可以使用任务权重来确定排序?
由于 Guava 的 ListeningExecutorService 是通过包装现有的 ExecutorService 来实现的,因此它通过拦截 execute() 方法来“装饰”任务。这意味着,如果我想在底层 ExecutorService 上使用自定义 PriorityQueue,我的比较器将“看到”装饰任务作为 ListenableFutureTask 对象而不是原始任务。
有没有办法掌握它包装的任务?以便队列的比较器可以使用任务权重来确定排序?
我假设你关心submit()
而不是execute()
?(见我回复的底部。)
使用ListeningExecutorService
from MoreExecutors.listeningDecorator
(您所指的包装器类型),您就不走运了。listeningDecorator
与大多数ExecutorService
实现一样,将任何输入包装submit
在FutureTask
. 此问题的正常解决方案是实现AbstractExecutorService
并覆盖newTaskFor
以返回自定义对象。这也应该在这里工作。您将基本上重新实现listeningDecorator
,这是一个相当琐碎的包装器AbstractListeningExecutorService
,它本身就是一个相当琐碎的包装器AbstractExecutorService
。
有两个并发症。(好吧,可能还有更多。我承认我没有测试过我建议的方法。)
AbstractListeningExecutorService
不允许您覆盖newTaskFor
. (为什么?我可以解释您是否想提交功能请求。)因此,您必须直接扩展AbstractExecutorService
,很大程度上复制(短)AbstractListeningExecutorService
实现。newTaskFor
必须返回一个ListenableFuture
那也是Comparable
。a 的明显选择ListenableFuture
是ListenableFutureTask
,但是那个类是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);
}