2016-04-06 5 views
4

私は、以下の非常に簡単コールバックインタフェースとPOJOクラス持っている:ステートレスコールバックをBlockingQueueに入れても安全ですか?

public interface Action{ 
    public void doAction(); 
} 

public class Person{ 
    private String name; 
    private String address; 
    //...etc 
    //GET, SET, toString 
} 

を私は次のようにそれを使用するつもりです:

public class ActionExecutor{ 

    private static final Logger logger = LogManager.getLogger(ActionExecutor.class); 
    private final BlockingQueue<Action> blockingQueue = new LinkedBlockingQueue(2000); 

    public void execute(final Person p){ 
     //modify state of p in some way 
     blockingQueue.put(new Action(){ 
      public void doAction(){ 
       logger.info("Execution started: " +p.toString); 
       //do some other job 
     }); 
    } 
} 

BlockingQueueここではproducer-を実装するために使用されます消費者。

質問:それはBlockingQueueから行動をとる消費者スレッドが正しいログメッセージを書き込むことが保証されていますか?私。 Personの正しい状態を観測していますか?しかし、私はそれについて厳密にはわかりません。

プロデューサによる変更とプロデューサによる読み取りの間に注文が発生することはないので、これは保証されません。

+1

いいえ、その保証はありません。 doActionメソッドが呼び出される前に、Person pの状態が変更される可能性があります。 p.toString()の文字列を取得し、その文字列をActionコンストラクタに渡してActionインスタンスのメンバとして格納することができます。 – bhspencer

+0

@bhspencer安全なスレッドセーフなオブジェクトしか公開できません。 –

+0

ここに公開することで何を意味するのか分かりません。私は問題がスレッドの安全性ではなく、状態に関するものだと考えています。アクションをキューに置くと、リファレンスを持つPersonはロックされていない状態になります。したがって、アクションが最終的に実行されたときに、アクションの作成時とは異なる状態になる可能性があります。 Person pはスレッドセーフである可能性がありますが、変更可能な場合はその状態が変更される可能性があります。 – bhspencer

答えて

3

答えはそれが依存するということです。

その後、Personインスタンスを変更しないと、保証されます。 in the docsを述べたように事前発生関係が、あります:

メモリー整合性効果:ほかの並行処理コレクションと同様、スレッド内 アクション前のアクセスに後続のBlockingQueue 起こる-前アクションにオブジェクトを配置します別のスレッドのBlockingQueueからその要素の 要素を削除することができます。

しかし、私はまだそれをしません。 Personインスタンスを変更した後で、のコールバックがキューに入れられた場合は、、次にという保証はありません。ロガーは、キューに追加されたときと同じくらい最新の状態を出力することが保証されていると言えます。

ので、消費者は、これらの変更が表示されます。

public void execute(final Person p){ 
    //modify state of p in some way 
    blockingQueue.put(new Action(){ 

でもないことの後に作られたもの。そして、あなたがnew Action()オブジェクトにそれを渡した後、pを守っているので、私はこれを避けるでしょう。代わりに、私は次のようなことをします:

​​

これで状態は最終変数に取り込まれます。現時点では、pの状態が何であっても、消費者はその値を見ることになります。

+0

匿名のActionクラスでtoStringを実行する代わりに、文字列をリストに追加するメソッドを実装することで、pの状態を追跡するpのメソッドを実装する必要があると思います。状態変化につき1つのメッセージを保証するための人物状態)と、おそらくgetStateChangeMes​​sage()などのパブリックメソッドで状態変更リストへのアクセスを提供する。 – DwB

+0

@DwB、私はPersonクラスがそれを行うのに適切な場所であるかどうかはわかりません。それを理解するのに十分な情報がない。それがシンプルなPOJOなら、それはおそらく正しい場所ではありません。しかし、それはこの質問の対象外です。 –

関連する問題