Are there any Listeners in Java to hand开发者_高级运维le that some thread have been ended? Something like this:
Future<String> test = workerPool.submit(new TestCalalble());
test.addActionListener(new ActionListener()
{
public void actionEnd(ActionEvent e)
{
txt1.setText("Button1 clicked");
}
});
I know, that it is impossible to deal like this, but I want to be notified when some thread ended.
Usually I used for this Timer class with checking state of each Future. but it is not pretty way. Thanks
There is CompletionService you can use.
CompletionService<Result> ecs
= new ExecutorCompletionService<Result>(e);
ecs.submit(new TestCallable());
if (ecs.take().get() != null) {
// on finish
}
Another alternative is to use ListenableFuture from Guava.
Code example:
ListenableFuture future = Futures.makeListenable(test);
future.addListener(new Runnable() {
public void run() {
System.out.println("Operation Complete.");
try {
System.out.println("Result: " + future.get());
} catch (Exception e) {
System.out.println("Error: " + e.message());
}
}
}, exec);
Personally, I like Guava solution better.
No. Such listener does not exist. But you have 2 solutions.
- Add code that notifies you that thread is done in the end of
run()
method - Use
Callable
interface that returns result of typeFuture
. You can ask Future what the status is and use blocked methodget()
to retrieve result
Here is a geekish listener. Highly unadvisible to use but, funny and clever
Thread t = ...
t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler(){
@Override
public void uncaughtException(Thread t, Throwable e) {
t.getThreadGroup().uncaughtException(t, e);//this is the default behaviour
}
protected void finalize() throws Throwable{
//cool, we go notified
//handle the notification, but be worried, it's the finalizer thread w/ max priority
}
});
The effect can be achived via PhantomRefernce better
hope you have a little smile :)
Side note: what you ask is NOT thread end, but task completion event and the best is overriding either decorateTask
or afterExecute
Without adding a lot of extra code you can make a quick listener thread yourself as follows:
//worker thread for doings
Thread worker = new Thread(new Runnable(){
public void run(){/*work thread stuff here*/}
});
worker.start();
//observer thread for notifications
new Thread(new Runnable(){
public void run(){
try{worker.join();}
catch(Exception e){;}
finally{ /*worker is dead, do notifications.*/}
}).start();
You can implement Observer Pattern to report completion.
public interface IRunComplete {
public void reportCompletion(String message);
}
Let the Thread caller implement this interface.
and in run() method you call this method at the end. So now you exactly knows when this thread gonna end.
Try it. I am actually using this and it's working fine.
You have a join() method defined by Thread class for that. However, you don't have direct visibility to a thread executing your Callable in concurrency API case..
Use this Example:
public class Main {
public static void main(String[] args) {
CompletionListener completedListener = count -> System.out.println("Final Count Value: " + count);
HeavyWorkRunnable job = new HeavyWorkRunnable(completedListener);
Thread otherThread = new Thread(job);
otherThread.start();
}
static class HeavyWorkRunnable implements Runnable {
CompletionListener completionListener;
public HeavyWorkRunnable(CompletionListener completionListener) {
this.completionListener = completionListener;
}
@Override
public void run() {
int count = 0;
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Clock Tick #"+i);
count += 1;
}
if (completionListener != null) {
completionListener.onCompleted(count);
}
}
}
@FunctionalInterface
interface CompletionListener {
void onCompleted(int count);
}
}
精彩评论