On this project, a Manager
performs event queuing, and to return the result of the event a callback is used (the callback does not extend Runnable
). The manager runs on a separate thread, dispatching the events. Once the events terminate, this same thread calls the callbacks. This means that the next event will not be dispatched before the callback of the previous event terminates. In order to avoid this, I though about having the manager create a new thread for each callback, and executing the callbacks there. How good is this solution in terms of design practices, and is there a better way to achieve this?
Asked
Active
Viewed 1.1k times
4

AmiguelS
- 805
- 2
- 10
- 28
2 Answers
6
A simple Callback
code:
import java.util.concurrent.*;
import java.util.*;
public class CallBackDemo{
public CallBackDemo(){
System.out.println("creating service");
ExecutorService service = Executors.newFixedThreadPool(10);
try{
for ( int i=0; i<10; i++){
Callback callback = new Callback(i+1);
MyCallable myCallable = new MyCallable((long)i+1,callback);
Future<Long> future = service.submit(myCallable);
//System.out.println("future status:"+future.get()+":"+future.isDone());
}
}catch(Exception err){
err.printStackTrace();
}
service.shutdown();
}
public static void main(String args[]){
CallBackDemo demo = new CallBackDemo();
}
}
class MyCallable implements Callable<Long>{
Long id = 0L;
Callback callback;
public MyCallable(Long val,Callback obj){
this.id = val;
this.callback = obj;
}
public Long call(){
//Add your business logic
System.out.println("Callable:"+id+":"+Thread.currentThread().getName());
callback.callbackMethod();
return id;
}
}
class Callback {
private int i;
public Callback(int i){
this.i = i;
}
public void callbackMethod(){
System.out.println("Call back:"+i);
// Add your business logic
}
}
output:
creating service
Callable:1:pool-1-thread-1
Call back:1
Callable:2:pool-1-thread-2
Call back:2
Callable:8:pool-1-thread-8
Call back:8
Callable:3:pool-1-thread-3
Call back:3
Callable:10:pool-1-thread-10
Callable:4:pool-1-thread-4
Call back:10
Callable:7:pool-1-thread-7
Call back:7
Callable:6:pool-1-thread-6
Call back:6
Callable:9:pool-1-thread-9
Callable:5:pool-1-thread-5
Call back:9
Call back:4
Call back:5
Summary:
- Replace
Manager
withExecutorService
of your preferred choice. - Either your can pass
Callaback
object toCallable/Runnable
object Or you can createCallback
object insideCallable/Runnable
. In my example, I have explicitly passedCallback
object toCallable
. Before returning the result,
Callable
object invokesCallback
method. If you want to block on proceeding further unless you get response from current event, just uncomment below line.System.out.println("future status:"+future.get()+":"+future.isDone());
I think you are going to avoid it and hence keep above line commented. You don't have to create new thread for Callback
method invocation. If you want to process Callback
event asynchronously, you can create one more ExecutorService
and submit the event.

Ravindra babu
- 37,698
- 11
- 250
- 211
2
I would have the thread which executes the task, also execute the call back. Instead of creating a Thread each time, I suggest you use an ExecutorService.
public static <T> void submit(ExecutorService service,
Callable<T> callable,
Consumer<T> callback) {
service.submit(() -> {
try {
callback.accept(callable.call());
} catch (Throwable t) {
// log the Throwable
}
});
}

Peter Lawrey
- 525,659
- 79
- 751
- 1,130
-
The task is executed "off-device". This is a manager for BLE communication. Once the response is received through BLE, the callback is executed. Hence the though of a creating a thread for it. – AmiguelS Apr 06 '16 at 11:12
-
@AmiguelS you can still use a thread pool for these callbacks. If you have a communication library this usually has a thread for callbacks/notification of messages. – Peter Lawrey Apr 06 '16 at 11:16