2016-04-06 45 views
3

このプロジェクトでは、Managerがイベントキューイングを実行し、イベントの結果を返すためにコールバックが使用されます(コールバックはRunnableを拡張しません)。マネージャーは別のスレッドで動作し、イベントをディスパッチします。イベントが終了すると、この同じスレッドがコールバックを呼び出します。これは、前のイベントのコールバックが終了する前に次のイベントがディスパッチされないことを意味します。これを避けるために、私はマネージャがそれぞれのコールバックのために新しいスレッドを作成し、そこにコールバックを実行させることについて考えます。このソリューションは、設計プラクティスの点でどの程度優れていますか?これを実現するためのよりよい方法はありますか?新しいスレッドでJavaコールバックを実行

答えて

5

シンプル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. あなたの好ましい選択肢のExecutorServiceManagerを交換してください。
  2. CallabackオブジェクトをCallable/Runnableオブジェクトに渡すか、またはCallbackオブジェクトをCallable/Runnable内に作成することができます。私の例では、Callbackオブジェクトを明示的にCallableに渡しました。
  3. 結果を返す前に、CallableオブジェクトはCallbackメソッドを呼び出します。あなたが現在のイベントからの応答を得ない限り、さらに進むことをブロックする場合は、以下の行のコメントを外してください。

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

私はあなたがそれを避けるので、コメント行の上に維持しようとしていると思います。 Callbackメソッド呼び出しのための新しいスレッドを作成する必要はありません。 Callbackイベントを非同期に処理する場合は、ExecutorServiceを1つ作成してイベントを送信します。

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 
     } 
    }); 
} 
+0

タスクは「オフデバイス」で実行されます。これは、BLE通信のマネージャです。応答がBLEを通じて受信されると、コールバックが実行されます。それゆえ、それのためのスレッドを作成します。 – AmiguelS

+0

@AmiguelSこれらのコールバックには、引き続きスレッドプールを使用できます。コミュニケーションライブラリを持っている場合、これは通常、メッセージのコールバック/通知のためのスレッドを持っています。 –

関連する問題