【问题标题】:Executing Java callback on a new thread在新线程上执行 Java 回调
【发布时间】:2016-04-06 10:56:19
【问题描述】:

在这个项目中,Manager 执行事件队列,并使用回调返回事件结果(回调不扩展 Runnable)。管理器在单独的线程上运行,分派事件。一旦事件终止,同一线程将调用回调。这意味着在上一个事件的回调终止之前,下一个事件不会被调度。为了避免这种情况,我考虑让管理器为每个回调创建一个新线程,并在那里执行回调。这个解决方案在设计实践方面有多好,是否有更好的方法来实现这一点?

【问题讨论】:

    标签: java multithreading callback


    【解决方案1】:

    一个简单的Callback代码:

    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
        }
    }
    

    输出:

    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
    

    总结:

    1. Manager 替换为您首选的ExecutorService
    2. 您可以将Callaback 对象传递给Callable/Runnable 对象,或者您可以在Callable/Runnable 中创建Callback 对象。在我的示例中,我已将Callback 对象显式传递给Callable
    3. 在返回结果之前,Callable 对象调用Callback 方法。如果您想阻止继续进行,除非您从当前事件中得到响应,请取消注释下面的行。

      System.out.println("future status:"+future.get()+":"+future.isDone());
      

    我认为你会避免它,因此保持上面的注释。您不必为Callback 方法调用创建新线程。如果要异步处理Callback事件,可以再创建一个ExecutorService并提交事件。

    【讨论】:

      【解决方案2】:

      我将拥有执行任务的线程,同时执行回调。建议不要每次都创建线程,而是使用 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
               }
           });
       }
      

      【讨论】:

      • 任务在“设备外”执行。这是 BLE 通信的管理器。一旦通过 BLE 接收到响应,就会执行回调。因此,为它创建了一个线程。
      • @AmiuelS 您仍然可以为这些回调使用线程池。如果你有一个通信库,这通常有一个用于回调/消息通知的线程。
      猜你喜欢
      • 1970-01-01
      • 2021-12-05
      • 1970-01-01
      • 2013-01-23
      • 2018-10-02
      • 1970-01-01
      • 2018-01-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多