我有:
ExecutorService
。Runnable
任务在中断后自行清理。Runnable
听众我的工作是在ExecutorService
上运行任务,然后在任务返回后的某个时间(通过ExecutorService
)或投掷时在同一return
上运行侦听器一个例外。我回到我的客户Future
,他(有时)打电话给cancel(true)
。
我的第一个想法是使用Guava的ListenableFuture.addListener
...但是这会在取消未来之后立即执行侦听器,而不是在任务返回之后执行。但是,如果在将监听器添加到将来之前完成任务,它确实具有良好的属性,即侦听器立即执行。我在下面的SSCCE中包含了这个解决方案。
从下面的示例中,我想要的内容如下:
Task Started
Task Canceling
Task Cancelled
**Listener Started**
实际得到的是:
Running
Canceling
**Listener**
Cancelled
在此示例中,我可以更改myMethod
内的任何内容,其余内容将提供给我。
public static void main(String[] args) {
Runnable task = new Runnable() {
public void run() {
try {
System.out.println("Task Started");
interruptableWork();
System.out.println("Task Completed");
} catch (InterruptedException e) {
System.out.println("Task Canceling");
cleanup();
System.out.println("Task Cancelled");
Thread.currentThread().interrupt();
}
}
private void interruptableWork() throws InterruptedException {
TimeUnit.SECONDS.sleep(2);
}
private void cleanup() {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException ignored) {
}
}
};
Runnable listener = new Runnable() {
public void run() {
System.out.println("**Listener Started**");
}
};
ExecutorService executor = Executors.newCachedThreadPool();
Future<?> future = myMethod(task, listener, executor);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ignored) {
}
future.cancel(true);
}
private static Future<?> myMethod(Runnable task, Runnable listener, ExecutorService executor) {
ListeningExecutorService listeningExecutor = MoreExecutors.listeningDecorator(executor);
ListenableFuture<?> future = listeningExecutor.submit(task);
future.addListener(listener, executor);
return future;
}
答案 0 :(得分:3)
我要尝试的第一件事就是将任务和监听器包裹在Runnable
中:
Runnable wrappedTask = new Runnable() {
public void run() {
try {
task.run();
} finally {
try {
listener.run();
} catch (RuntimeException e)
// log failure?
}
}
}
};
executor.submit(wrappedTask);
(当然,代替记录侦听器失败,你可以让失败传播。我选择记录(a)以便侦听器失败不会覆盖任务失败和(b)以便侦听器失败。 t覆盖任务成功。)