3

クラスには、同期的に実行されるいくつかのメソッドがあります。最初のアイデアは、それをラップし、switch enum を使用してどの関数を呼び出すかを決定することでした。しかし、呼び出されるメソッドごとに、ラッパー クラスに新しいメソッドと新しい列挙型が必要でした。次のようになります。

public class QueuedShow implements InterfaceShowAlert, Runnable {
    private Class Action {
       String param1;
       public static enum ActionEnum{
          NEW, CHECK, UPDATE, DELETE, DISPLAY;
       }
       public ActionEnum todo;
       public Action(ActionEnum todo, Object param){
          this.todo=todo;
          this.param1=param;
       }
    }
    private BlockingQueue<Action> actionList;
    public void run(){
       while(true){
           Action action=actionList.take(); //THIS waits until queue isn't empty
           switch(action.todo){
           case NEW: //Call original function
              ....
           }
       }
    }
    public void new(String param){
       actionList.add(new Action(NEW, param));
    }
}

その後、リフレクションについて学び、新しいアイデアを思いつきました。つまり、メソッドを直接呼び出すのではなく、文字列を使用してメソッドを呼び出します。ラッパー クラスは文字列を読み取って解析し、リフレクションを使用してクラスとそれを含むメソッドを取得します。パラメータと Method オブジェクトをクラスに入れ、それをキューに入れます。クラスは、列挙型を使用して切り替える代わりに、Method.invoke(params) を使用するようになりました。しかし、これの問題は、コンパイラ時の型チェックが失われることです。

もちろん、これはすべて void のメソッドに対してのみ機能しますが、もちろん Future クラスを使用して値を返すこともできます。

現在、同期呼び出しを非同期呼び出しに切り替えることを既に実装しているフレームワークはありますか、またはこれを行う他の方法を知っていますか。

4

3 に答える 3

5

推奨される方法は次のとおりです。

abstract public class Action<T> implements Runnable {
  private final T param;

  public Action(T param) {
    this.param = param;
  }

  @Override
  public final void run() {
    work(param);
  }

  abstract protected void work(T param);
}

と:

ExecutorService exec = Executors.newSingleThreadExecutor();
while (/* more actions need to be done */) {
  exec.submit(action);
}
exec.shutdown();
exec.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
于 2010-03-11T07:29:52.743 に答える
4

これを処理する通常の方法は、ここに示すように、Java 5 executors フレームワークを使用することです。これにより、同期実装と非同期実装の両方に同じパターンを使用できるようになり、使用する ExecutorService を選択するだけで済みます。

于 2010-03-11T07:23:11.337 に答える
1

しかし、それは krosenvoid と同じことです。つまり、work(param) メソッドを実装するすべてのメソッドにラッパー クラスが必要です。

Stringメソッド名とObjectパラメーターに渡す場所で、完全に動的で反射的なものを選びます。Java は (Groovy のような動的言語とは異なり) 静的に型付けされるため、恐ろしいことになり、おそらくキャストでいっぱいになりますが、それは可能です。

現在のソリューションでは、非同期メソッドが でリストされていますenums。そのため、コードを変更しない限り、完全に動的でも拡張可能でもありません。つまり、enum新しいメソッドごとに新しい を追加する必要があります。

public static enum ActionEnum{
          NEW, CHECK, UPDATE, DELETE, DISPLAY;
}

よろしければ、他の回答で提案されているように、Actionorを使用しても問題ないはずです。新しいメソッドごとに、新しいorを記述して、メソッド呼び出しが静的に定義されるようにCallableする必要があります。ActionCallable

 protected void work(String param)
 {
      myObject.theMethodToDispatch( param );
 }

もう少し定型的なコードであることに同意しますが、それでもかなり小さいです。大きな利点は、コードがリフレクティブではなく(そしてキャストがないはずです)、静的に型付けされた言語の利点があることです。メソッド名をリファクタリングでき、型パラメーターが一致しない場合はコンパイラーが警告します。

于 2010-03-11T09:30:37.100 に答える