Java:リスナーをに追加する方法はありExecutor
ますか?Future
いくつかのGUIステータスを更新するために、監視しようとしているsのコレクションがあります。現在、送信/完了したタスクに違いがあるかどうかをバックグラウンドスレッドでチェックしていますが、これをwhile(true){}
ブロックで行っているため、このアプローチは好きではありません。
5 に答える
GUIツールキットに応じてSwingWorkersまたは同様のクラスを使用して、タスクが完了したときに通知を受け取ることができます。
残念ながら、それを行う方法はありません。
代わりに、GoogleのListenableFuture<V>
インターフェースを使用してください。
または、C#やTPLなど、非同期サポートが優れている言語を使用します。
タスクの完了時に何かを実行したい場合は、それをタスク自体に追加します。
public static <T> void addTask(Callable<T> tCall) {
executor.submit(new Runnable() {
public void run() {
T t = tCall.call();
// what you want done when the task completes.
process(t);
}
});
}
タスクを送信するには、Executorの代わりにjava.util.concurrent.ExecutorCompletionServiceを使用します。最近完了したタスクを返すメソッドtake()があります。ループで呼び出す追加のスレッド(またはSwingWorker)を開始take()
し、その結果でGUIステータスを更新します。
@PeterLawreyの答えに似たようなことをしました。
呼び出し可能オブジェクトのメンバー変数としてリスナーを追加し、呼び出し可能オブジェクトが結果を返す直前にそのリスナーを呼び出しました。
したがって、リスナーインターフェイスがあります。
@FunctionalInterface
public interface Listener<T> {
void notify(T result);
}
それをメンバー変数として持つCallable:
public class CallbackCallable implements Callable<String>{
private Listener<String> listener;
@Override
public String call() throws Exception {
// do some stuff
if (listener != null)
listener.notify("result string");
return "result string";
}
public void setListener(Listener<String> listener) {
this.listener = listener;
}
}
そして、アプリケーションでは、リスナーの実装に、結果で実行したいことを渡します。
public static void main(String[] args) {
ExecutorService es = Executors.newSingleThreadExecutor();
System.out.println("This is thread: " + Thread.currentThread().getName());
CallbackCallable myCallable = new CallbackCallable();
myCallable.setListener(r -> {
// process your callable result here
System.out.println("Got from Callable: " + r);
System.out.println("This is thread: " + Thread.currentThread().getName());
});
es.submit(myCallable);
}
覚えておく必要があるのは、実装がCallableと同じスレッドで実行されることだけです。これを実行すると、次のことがわかります。
This is thread: main
Got from Callable: result string
This is thread: pool-1-thread-1