Java Swing - Updating the view from multiple thread - java

This question may be duplicated because I found a lot of similar question, but not the answer to my problem: I need to update the view of my SWING application from different SwingWorker.
I have a View class with a JTextArea and a JTable that i need to update during the execution of the Threads. The view also has a Start button that launch all the threads.
The controller listens for the button to be clicked then launch the threads:
public class MonitorPageController {
private MonitorPage monitorPage;
private List<Mission> missions;
class StartButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < missions.size(); i++) {
MyWorker worker = new MyWorker(missions.get(i));
worker.execute();
}
}
}
}
Then I have MyWorker class that manage the model:
public class MyWorker extends SwingWorker<Integer, String> {
private Mission m;
//<dec>
Block block1 = new Block();
Block block2 = new block();
Block block3 = new Block();
Block block4 = new Block();
public MyWorker(Mission mission) {
this.m = mission;
}
#Override
protected Integer doInBackground() throws Exception {
//<exe>
block1.addObserver(block2);
block2.addObserver(block3);
block3.addObserver(block4);
block4.addObserver(block2);
block1.update(null, m);
return 4;
}
}
In the end I have the Block class that is where I need to update the GUI (JTable and JTextArea):
public class Block extends Node implements Observer {
public Mission run(Mission m) {
m.setStatus(Mission.UNEXECUTED);
// HERE I WANT TO NOTIGY THE VIEW OF THE CHANGE OF STATUS OF THE MISSION
return m;
}
#Override
public void update(Observable o, Object arg) {
Mission m = this.run((Mission) arg);
setChanged();
notifyObservers(m);
}
}
EDIT: Mission is a simple class with the attribute: int status
I already tried with another observer pattern: I setted the mission as observable and the MonitorPageController as the observer. Then in the setter method of the status in class Mission I added the setChanged() and the notifyObservers() methods. In the end in the Observer (MonitoPageController) I implemented the update() method to call the view and update the gui.
I liked this way because it's clean and easy to implement, but I don't now why, after calling the notifyObserver() nothing was happening, so I discarded this solution, even if it seems to be the right one

Update the UI calling SwingUtilities.invokeLater() :
public class Block extends Node implements Observer {
public Mission run(Mission m) {
m.setStatus(Mission.UNEXECUTED);
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
//UPDATE UI HERE
}
});
return m;
}
#Override
public void update(Observable o, Object arg) {
Mission m = this.run((Mission) arg);
setChanged();
notifyObservers(m);
}
}

I found a possible solution, maybe there better ideas, but this works for now:
Creating the SwingWorker in MonitorPageController I changed the constructor passing the istance of the MonitorPageController too.
MyWorker worker = new MyWorker(misssions.get(i), this);
Then in MyWorker class when I create Block1, Block2, ...I pass them the istance of the MyWorker:
Block block1 = new Block(this);
Block block2 = new Block(this);
....
In the same class (MyWorker) I created a method:
public void log(Mission m, String s) {
controller.log(m, s);
}
Controller is the istance of the MonitorPageController that created the worker.
Now the inside block class, when I want to notify the change of status, I can call:
parentWorker.log(mission, "some string");
In the end the log() method in the MonitorPageController calls the view method to update the components...by now it seems to work...

Related

Async callback and listener

I have the following interfaces:
public interface NumberOfCellsListener {
public void numberOfCellsChanged(int patientId, int numOfCells);
}
public interface NumberOfCells {
public void register(NumberOfCellsListener listener);
public int numOfCells(int patientId);
}
public interface ProbabilityOfCancer {
//this may be a time consuming calculation
public double probability(int patientId, int numOfCells, bool gender, double weight);
}
This is the structure of my cancer probability calculator. My task is to implement this such that it can be called asynchronously due to the time consuming nature of the calculations. I am new to Java, can anyone please guide me on how to implement these interfaces? I am not sure about the structure i.e. what goes where. I am guessing I should get the new number of cells from the method numberOfCellsChanged in NumberOfCellsListener's implementation. But since it is a void method, I am not sure what to do.
An Interface method that does not return something usually has the function of changing the internal state, or of using some other means of output (for example to print something to the console, send something over a network, or save it to a database or file.).
As for the specific interfaces:
A Listener as in NumberOfCellsListener is meant to be installed ('registered') with an object that calls a listener's method, in case a specific event occures. In your case, based on the interface name, I would assume, that your method is called, when the number of cells of some object changes. So the question for you should be, what that information (at that point) requires you to do, and do that in the method.
A class implementing NumberOfCells is supposed to make true of the above statement. It has a register method, that should put the listener in some sort of collection (maybe a List - e.g. an ArrayList?) and then, when a certain event occures, invoke all the list's listener's numberOfCellsChanged-methods.
So an example implementation could be:
public class NumberOfCellsPrinter implements NumberOfCellsListener {
public void numberOfCellsChanged(int patientId, int numOfCells) {
System.out.println("The number of cells for parentId:" + parentId + " has changed to " + numOfCells + ".");
}
}
...
public class PetriDish implements NumberOfCells {
private ArrayList<NumberOfCellsListener> listeners = new ArrayList<>();
private int numOfCells = 0;
public void register(NumberOfCellsListener listener) {
if (listener != null && !listeners.contains(listener)) {
listeners.add(listener);
}
}
public int numOfCells(int patientId) {
for (NumberOfCellsListener listener : listeners) {
listener.numberOfCellsChanged(parentId, numOfCells);
}
return numOfCells;
}
}
While this example is totally meaningless, and will always produce 0 as numOfCells, it should demonstrate the idea of listeners.
It is very important, that you familiarize yourself with the risks and traps concerning parallelism, since this is a key factor of your objective.
Try the following to learn about async callbacks in Java. You can find more tutorials and explanations here
// Java program to illustrate Asynchronous callback
interface OnGeekEventListener {
// this can be any type of method
void onGeekEvent();
}
class B {
private OnGeekEventListener mListener; // listener field
// setting the listener
public void registerOnGeekEventListener(OnGeekEventListener mListener)
{
this.mListener = mListener;
}
// My Asynchronous task
public void doGeekStuff()
{
// An Async task always executes in new thread
new Thread(new Runnable() {
public void run()
{
// perform any operation
System.out.println("Performing operation in Asynchronous Task");
// check if listener is registered.
if (mListener != null) {
// invoke the callback method of class A
mListener.onGeekEvent();
}
}
}).start();
}
// Driver Program
public static void main(String[] args)
{
B obj = new B();
OnGeekEventListener mListener = new A();
obj.registerOnGeekEventListener(mListener);
obj.doGeekStuff();
}
}
class A implements OnGeekEventListener {
#Override
public void onGeekEvent()
{
System.out.println("Performing callback after Asynchronous Task");
// perform some routine operation
}
// some class A methods
}

Thread field inside a class that implements Runnable, which instantiates said class

In my school's program solutions for multithreading problems and exercises, classes that implement the Runnable interface are usually given a Thread field, which is automatically instantiated in the following example:
protected Thread thr = new Thread(this);
This field is subsequently used as a means of controlling the Thread over which the class itself is instantiated. For example:
public void stop() {
if (thr != null) thr.interrupt();
}
Which is then used to interrupt Thread objects made with the Runnable class.
A full class example, ported directly from an aforementioned solution, is given below:
package hokej;
import java.awt.Color;
public abstract class AktFigura extends Figura implements Runnable {
protected Thread nit = new Thread(this);
private int tAzur;
private boolean radi;
public AktFigura(Scena s, int xx, int yy,
Color b, int t) {
super(s, xx, yy, b); tAzur = t;
}
protected abstract void azurirajPolozaj();
public void run() {
try {
while (!Thread.interrupted()) {
synchronized (this) {
if (!radi) wait();
}
azurirajPolozaj();
scena.repaint();
Thread.sleep(tAzur);
}
} catch (InterruptedException ie) {}
}
public synchronized void kreni() {
radi = true; notify();
}
public void stani() { radi = false; }
public void prekini() {
if (nit != null) nit.interrupt();
}
}
My question is this: How does this work?
Shouldn't the Thread field be a separate object from the object made by calling new Thread(class); in other parts of the program (hence the keyword's name - new)?
Or is this simply a special case that the Java interpreter recognizes in a certain way?
Another question would be the viability of this design as a control method. Is there any simpler/more efficient alternative for controlling a Runnable's thread?
How does this work?
The Thread constructor takes a Runnable, Thread implements this interface. this refers to a Thread instance. So, the statement Thread thr = new Thread(this) is valid, but this practice should be avoided.
Is there any simpler/more efficient alternative for controlling a Runnable's thread?
Thread thread = new Thread(new AktFiguraImpl());
thread.start();
You could control a thread by a class specifically designed for that purpose.
class ThreadController {
public ThreadController(Thread thread, AktFigura figura) { ... }
// methods to manipulate the thread
}

How to return a value from a Thread to another class

I am currently writing a java application to do a brute force attack on an MD5 hash. I made a JFrame that takes the uses hash input.
for example i hashed the word "password" to MD5. (seen in picture 1) when the JButton is clicked
it will send the hash to a Comparative class that will iterate trough all the possibilities in sequential order. IE go from AAAAAAAA. then to AAAAAAAB and so on. and hashes them. If the hash of the possibility matched the hash of the word "password". A dialog box will appear informing the user that a match has been found.
My problem is that i don't know how to return a value from a thread in a class that implements Runnable to the GUI class without using setters and getters.
public void actionPerformed(ActionEvent e)
{
if(e.getSource().equals(bruteForceButton))
{
enterLabel.setText("Brute force in process");
String enteredHash = input.getText();
int lengthOfPass = (int) length.getSelectedItem();
//Send the information to the comparative class
HashComparative comp = new HashComparative();
comp.setHash(enteredHash);
comp.setLengthOfPass(lengthOfPass);
Thread t1 = new Thread(comp);
t1.start();
hash.setText(comp.getHash());
}
this starts the thread sending the appropriate data to the comparative class.
And here is the other class.
public class HashComparative implements Runnable
{
private String h;
private int l;
private Thread thread;
public void start()
{
thread = new Thread(this, "");
thread.start();
}
#Override
public void run()
{
try
{
//CODE WILL GO HERE TO COMPUTE HASHES
setHash(h);
}
catch(Exception e)
{
e.printStackTrace();
}
}
public void setHash(String h)
{
this.h = h;
}
//Returns the hash currently being compared
public String getHash()
{
return h;
}
}
While the brute force is in operation. I want the display the hashes that it tries by sending the hash string back to the GUI class and set the text to a JLabel. For Example
I have looked online but can't find an answer to this. Any help will be appreciated
What you need to implement is rather Callable instead of Runnable as this interface allows you to return a value which is what you want here. As you can only provide Runnable to a Thread, you need to use a pool thread instead, that you can create from Executors. It will allow you to submit your task as a Callable or a Runnable, and then get a Future to be able to wait until the task is completed successfully or not.
In your case you can create a pool of only one thread using Executors.newSingleThreadExecutor()
ExecutorService executor = Executors.newSingleThreadExecutor();
...
Then your class HashComparative will be:
public class HashComparative implements Callable<String> {
private final String enteredHash;
private final int lengthOfPass;
public HashComparative(final String enteredHash, final int lengthOfPass) {
this.enteredHash = enteredHash;
this.lengthOfPass = lengthOfPass;
}
#Override
public String call() throws Exception {
//CODE WILL GO HERE TO COMPUTE HASHES
return h;
}
...
}
And finally you will submit your task as next:
HashComparative comp = new HashComparative(enteredHash, lengthOfPass);
Future<String> future = executor.submit(comp);
hash.setText(future.get());
What can be used to display the unmatching hashes?
The design pattern that matches the best with this kind of need is Observer. Indeed here you want to make your UI observes the progress of your computation. Out of the box, you have Observable and Observer that you can use to implement this pattern.
So here for the sake of simplicity, you could make your class HashComparative extends Observable to be able to notify the Observers (your UI here) any time a new hash is being processed.
public class HashComparative extends Observable implements Callable<String> {
private String h;
...
public void setHash(String h) {
this.h = h;
setChanged();
notifyObservers();
}
public String getHash() {
return h;
}
}
Then in your UI, you can change the text accordingly by implementing Observer
final HashComparative comp = new HashComparative(enteredHash, lengthOfPass);
comp.addObserver(new Observer() {
#Override
public void update(final Observable o, final Object arg) {
HashComparative hc = (HashComparative)o;
hash.setText(hc.getHash());
}
});
If it goes too fast, you could also use a ScheduledExecutorService to only change the hash displayed after a given amount of time. You could for example create it using Executors.newSingleThreadScheduledExecutor() to have only one thread then refresh the hash as next:
final HashComparative comp = new HashComparative(enteredHash, lengthOfPass);
scheduler.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
hash.setText(comp.getHash());
}
}, 1L, 1L, TimeUnit.SECONDS);
This will refresh the hash displayed every second. With this approach you have no need to extend Observable anymore, you will only need to make h volatile as it will be modified and accessed by several threads concurrently
public class HashComparative implements Callable<String> {
private volatile String h;
...
}

How can I pass a parameter to a Java Thread?

Can anyone suggest to me how I can pass a parameter to a thread?
Also, how does it work for anonymous classes?
You need to pass the parameter in the constructor to the Runnable object:
public class MyRunnable implements Runnable {
public MyRunnable(Object parameter) {
// store parameter for later user
}
public void run() {
}
}
and invoke it thus:
Runnable r = new MyRunnable(param_value);
new Thread(r).start();
For Anonymous classes:
In response to question edits here is how it works for Anonymous classes
final X parameter = ...; // the final is important
Thread t = new Thread(new Runnable() {
p = parameter;
public void run() {
...
};
t.start();
Named classes:
You have a class that extends Thread (or implements Runnable) and a constructor with the parameters you'd like to pass. Then, when you create the new thread, you have to pass in the arguments, and then start the thread, something like this:
Thread t = new MyThread(args...);
t.start();
Runnable is a much better solution than Thread BTW. So I'd prefer:
public class MyRunnable implements Runnable {
private X parameter;
public MyRunnable(X parameter) {
this.parameter = parameter;
}
public void run() {
}
}
Thread t = new Thread(new MyRunnable(parameter));
t.start();
This answer is basically the same as this similar question: How to pass parameters to a Thread object
via constructor of a Runnable or Thread class
class MyThread extends Thread {
private String to;
public MyThread(String to) {
this.to = to;
}
#Override
public void run() {
System.out.println("hello " + to);
}
}
public static void main(String[] args) {
new MyThread("world!").start();
}
This answer comes very late, but maybe someone will find it useful. It is about how to pass a parameter(s) to a Runnable without even declaring named class (handy for inliners):
String someValue = "Just a demo, really...";
new Thread(new Runnable() {
private String myParam;
public Runnable init(String myParam) {
this.myParam = myParam;
return this;
}
#Override
public void run() {
System.out.println("This is called from another thread.");
System.out.println(this.myParam);
}
}.init(someValue)).start();
Of course you can postpone execution of start to some more convenient or appropriate moment. And it is up to you what will be the signature of init method (so it may take more and/or different arguments) and of course even its name, but basically you get an idea.
In fact there is also another way of passing a parameter to an anonymous class, with the use of the initializer blocks. Consider this:
String someValue = "Another demo, no serious thing...";
int anotherValue = 42;
new Thread(new Runnable() {
private String myParam;
private int myOtherParam;
// instance initializer
{
this.myParam = someValue;
this.myOtherParam = anotherValue;
}
#Override
public void run() {
System.out.println("This comes from another thread.");
System.out.println(this.myParam + ", " + this.myOtherParam);
}
}).start();
So all happens inside of the initializer block.
When you create a thread, you need an instance of Runnable. The easiest way to pass in a parameter would be to pass it in as an argument to the constructor:
public class MyRunnable implements Runnable {
private volatile String myParam;
public MyRunnable(String myParam){
this.myParam = myParam;
...
}
public void run(){
// do something with myParam here
...
}
}
MyRunnable myRunnable = new myRunnable("Hello World");
new Thread(myRunnable).start();
If you then want to change the parameter while the thread is running, you can simply add a setter method to your runnable class:
public void setMyParam(String value){
this.myParam = value;
}
Once you have this, you can change the value of the parameter by calling like this:
myRunnable.setMyParam("Goodbye World");
Of course, if you want to trigger an action when the parameter is changed, you will have to use locks, which makes things considerably more complex.
I know that I'm a few years late, but I came across this issue and took an unorthodox approach. I wanted to do it without making a new class, so this is what I came up with:
int x = 0;
new Thread((new Runnable() {
int x;
public void run() {
// stuff with x and whatever else you want
}
public Runnable pass(int x) {
this.x = x;
return this;
}
}).pass(x)).start();
You can either extend the Thread class or the Runnable class and provide parameters as you want. There are simple examples in the docs. I'll port them here:
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
PrimeThread p = new PrimeThread(143);
p.start();
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
To create a thread you normally create your own implementation of Runnable. Pass the parameters to the thread in the constructor of this class.
class MyThread implements Runnable{
private int a;
private String b;
private double c;
public MyThread(int a, String b, double c){
this.a = a;
this.b = b;
this.c = c;
}
public void run(){
doSomething(a, b, c);
}
}
Either write a class that implements Runnable, and pass whatever you need in a suitably defined constructor, or write a class that extends Thread with a suitably defined constructor that calls super() with appropriate parameters.
In Java 8 you can use lambda expressions with the Concurrency API & the ExecutorService as a higher level replacement for working with threads directly:
newCachedThreadPool() Creates a thread pool that creates new threads
as needed, but will reuse previously constructed threads when they are
available. These pools will typically improve the performance of programs that execute many short-lived asynchronous tasks.
private static final ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(() -> {
myFunction(myParam1, myParam2);
});
See also executors javadocs.
As of Java 8, you can use a lambda to capture parameters that are effectively final. For example:
final String param1 = "First param";
final int param2 = 2;
new Thread(() -> {
// Do whatever you want here: param1 and param2 are in-scope!
System.out.println(param1);
System.out.println(param2);
}).start();
Parameter passing via the start() and run() methods:
// Tester
public static void main(String... args) throws Exception {
ThreadType2 t = new ThreadType2(new RunnableType2(){
public void run(Object object) {
System.out.println("Parameter="+object);
}});
t.start("the parameter");
}
// New class 1 of 2
public class ThreadType2 {
final private Thread thread;
private Object objectIn = null;
ThreadType2(final RunnableType2 runnableType2) {
thread = new Thread(new Runnable() {
public void run() {
runnableType2.run(objectIn);
}});
}
public void start(final Object object) {
this.objectIn = object;
thread.start();
}
// If you want to do things like setDaemon(true);
public Thread getThread() {
return thread;
}
}
// New class 2 of 2
public interface RunnableType2 {
public void run(Object object);
}
You can derive a class from Runnable, and during the construction (say) pass the parameter in.
Then launch it using Thread.start(Runnable r);
If you mean whilst the thread is running, then simply hold a reference to your derived object in the calling thread, and call the appropriate setter methods (synchronising where appropriate)
There is a simple way of passing parameters into runnables.
Code:
public void Function(final type variable) {
Runnable runnable = new Runnable() {
public void run() {
//Code adding here...
}
};
new Thread(runnable).start();
}
No you can't pass parameters to the run() method. The signature tells you that (it has no parameters). Probably the easiest way to do this would be to use a purpose-built object that takes a parameter in the constructor and stores it in a final variable:
public class WorkingTask implements Runnable
{
private final Object toWorkWith;
public WorkingTask(Object workOnMe)
{
toWorkWith = workOnMe;
}
public void run()
{
//do work
}
}
//...
Thread t = new Thread(new WorkingTask(theData));
t.start();
Once you do that - you have to be careful of the data integrity of the object you pass into the 'WorkingTask'. The data will now exist in two different threads so you have to make sure it is Thread Safe.
One further option; this approach lets you use the Runnable item like an asynchronous function call. If your task does not need to return a result, e.g. it just performs some action you don't need to worry about how you pass back an "outcome".
This pattern lets you reuse an item, where you need some kind of internal state. When not passing parameter(s) in the constructor care is needed to mediate the programs access to parameters. You may need more checks if your use-case involves different callers, etc.
public class MyRunnable implements Runnable
{
private final Boolean PARAMETER_LOCK = false;
private X parameter;
public MyRunnable(X parameter) {
this.parameter = parameter;
}
public void setParameter( final X newParameter ){
boolean done = false;
synchronize( PARAMETER_LOCK )
{
if( null == parameter )
{
parameter = newParameter;
done = true;
}
}
if( ! done )
{
throw new RuntimeException("MyRunnable - Parameter not cleared." );
}
}
public void clearParameter(){
synchronize( PARAMETER_LOCK )
{
parameter = null;
}
}
public void run() {
X localParameter;
synchronize( PARAMETER_LOCK )
{
localParameter = parameter;
}
if( null != localParameter )
{
clearParameter(); //-- could clear now, or later, or not at all ...
doSomeStuff( localParameter );
}
}
}
Thread t = new Thread(new MyRunnable(parameter));
t.start();
If you need a result of processing, you will also need to coordinate completion of MyRunnable when the sub-task finishes. You could pass a call back or just wait on the Thread 't', etc.
Specially for Android
For callback purposes I usually implement my own generic Runnable with input parameter(s):
public interface Runnable<TResult> {
void run(TResult result);
}
Usage is simple:
myManager.doCallbackOperation(new Runnable<MyResult>() {
#Override
public void run(MyResult result) {
// do something with the result
}
});
In manager:
public void doCallbackOperation(Runnable<MyResult> runnable) {
new AsyncTask<Void, Void, MyResult>() {
#Override
protected MyResult doInBackground(Void... params) {
// do background operation
return new MyResult(); // return resulting object
}
#Override
protected void onPostExecute(MyResult result) {
// execute runnable passing the result when operation has finished
runnable.run(result);
}
}.execute();
}
Create a local variable in your class that extends Thread or implements Runnable.
public class Extractor extends Thread {
public String webpage = "";
public Extractor(String w){
webpage = w;
}
public void setWebpage(String l){
webpage = l;
}
#Override
public void run() {// l is link
System.out.println(webpage);
}
public String toString(){
return "Page: "+webpage;
}}
This way, you can pass a variable when you run it.
Extractor e = new Extractor("www.google.com");
e.start();
The output:
"www.google.com"
First I want to point out that other answers are true.
However, using the parameter in the constructor may not be the best idea for all of you.
In many scenarios you will want to use "Anonymous Inner Class", and override the run() method, because defining specific class for every use is painful.
(new MyRunnable(){...})
And at the time you create that Runnable, the parameter may not be available to you to pass it in the constructor. If for example, you pass this object to a method, that will perform some work in separate thread and then call your runnable, applying the result from that work to it.
In that case, using a method like this one:
public MyRunnable withParameter(Object parameter), may turn out to be far more useful choice.
I do not claim that this is the best solution to the problem, but it will get the job done.

How to notify all observers without holding the thread?

I have a thread inside a class like this-
import java.util.Observable;
public class Download extends Observable {
private int state = 0;
private final Thread myThread = new Thread(() -> {
/*
some work to do here
*/
setChanged();
notifyObservers(state);
});
public void download(int state) {
if (!myThread.isAlive()) {
this.state = state;
myThread.start();
}
}
public Thread getThread() {
return myThread;
}
public static void MyMethod() throws InterruptedException {
Download down = new Download();
down.addObserver((Observable ob, Object dat) -> {
System.out.println(ob);
if ((int) dat == 1) {
down.download(2);
} else {
System.out.println("success");
}
});
down.download(1);
down.getThread().join();
}
public static void main() throws InterruptedException {
MyMethod();
}
}
The problem is I never get it to print the "success" message.
I assume, it is because all observers are being notified from inside of MyThread. So when down.download(2) is called from the observer inside MyMethod(), the previous thread is still running and the call is ignored.
How can I notify all observers from the main thread, not from the myThread?
You are calling down.download(2) from within the execution of MyThread, therefore the thread is still alive which means that your download method does nothing because of if(!myThread.isAlive()).
I would recommend you to use the Executor framework and Listenable Futures from Guava instead of creating threads manually. Example code from the Guava wiki:
ListeningExecutorService service =
MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
ListenableFuture<Explosion> explosion = service.submit(new Callable<Explosion>() {
public Explosion call() {
return pushBigRedButton();
}
});
Futures.addCallback(explosion, new FutureCallback<Explosion>() {
// we want this handler to run immediately after we push the big red button!
public void onSuccess(Explosion explosion) {
walkAwayFrom(explosion);
}
public void onFailure(Throwable thrown) {
battleArchNemesis(); // escaped the explosion!
}
});
Note that Futures.addCallback(..) also has an overload which allows you to determine which executor should execute the callback, this seems to be what you want.

Categories