2016-12-30 14 views
0

私はデータを含むオブジェクトを持っていますが、このオブジェクトでアクション(実行可能なメソッドとのインターフェイス)をキューに入れています(そのメソッドはオブジェクトのデータをメソッド内で使用します)別のスレッドから実行されます。Javaマルチスレッドの問題

オブジェクトをアクションキューに送信した後にロックしたいと思います(メインスレッドから)。

他のスレッドがアクションキューを介して処理する前に、オブジェクトのデータを変更したくないためです。

そして、アクションキューが処理されると、他のスレッドからロックを解除したいと思います。

コードイラスト:

// THREAD 1 
final Object object = getObjectFromSomeWhere(); 

// lock the object here 

concurrentActionQueue.add(new Action() { 
     @Override 
     public void execute() { 
      // will be executed from THREAD 2 
      // do something with object 

      //unlock here once the data is processed 

     } 

あなたは、私はアクションにオブジェクトのコピーを送った可能性がありますが、私のオブジェクトは非常に大きなデータを含むされ、コピーが、私がすることはできませんので、多くの時間を取っていると言うでしょう。

lock()メソッドとunlock()メソッドをオブジェクトにハードコードしないと、これを行う方法はありますか?

+0

消費者プロデューサーパターンおそらく?ここでは、非常に単純な(最高ではない)[チュートリアル](https://www.tutorialspoint.com/javaexamples/thread_procon.htm)から始める – AntJavaDev

答えて

0

あなたはすべてのメインスレッドの実行をロックしたい場合は、CountDownLatchを使用することができます。

// THREAD 1 
final Object object = getObjectFromSomeWhere(); 

final CountDownLatch latch = new CountDownLatch(1); 

concurrentActionQueue.add(new Action() { 
     @Override 
     public void execute() { 
      // will be executed from THREAD 2 
      // do something with object 

      latch.countDown(); 
     } 
} 

latch.await(); 

あなたは、他のスレッドから変更されたオブジェクトデータをロックしますが、利用できるスレッドの実行を残しておきたい場合は、あなたはObjectクラスの中でそれを行う必要があります。私はそれがオブジェクトではないと信じています。たとえば、オブジェクトへのアクセス権を持つThreadへの参照を渡すことができ、その内部をチェックするとThread.currentThread() == mAllowedThread;がオブジェクトを変更できるこのスレッドであることを知ることができます。

また、オブジェクトにパッケージローカルのセッターがあり、セッターにアクセスできるラッパーをアクションに渡すなど、それに対処するためにいくつかのOO方法を使用できます。私はあなたの実際の問題を見ていないので、解決策は何かを言うのは難しいです。私の提案のいくつかがあなたにも役立つことを願っています。

+0

私の問題は、私が自分のデータ(オブジェクト)をそれは良いフォーマットです。しかし、データは永続的に変更され、データはもはや危険な形式(スレッド1から変更されている)になっていない瞬間に実行される可能性があります。私のスレッド2はレンダラーであり、そのメッシュのための整然としたデータが必要です。 – aqww

+0

"ロック/アンロック"オブジェクトの下ではどういう意味ですか?オブジェクトを変更しようとすると、他のスレッドはどのようにふるまうべきですか? –

+0

もう一つの可能​​性があります。一つは、データを変更する前にロックを解除するまで待たなければならないスレッドです。あるいは、データがロックされている間にすべての変更がキューに入れられ、ロックされなくなったときに実行されるものをハードコードすることができます。 – aqww

0

スレッド間の共通の参照のみがオブジェクトのロックであるため、オブジェクトを変更する必要があります。あなたのオブジェクトを変更したくない場合は、タスクを実行するためにcountdownラッチを使うヘルパークラスを書くことができます。そして、あなたのすべてのスレッドの間でこのヘルパークラスリファレンスを渡してください。 これがあなたが探しているものかどうかを確認してください -

final YourObject object = getObjectFromSomeWhere(); 

class HelperObject { 
YourObject object; 
public HelperObject(YourObject object){ 
this.object = object; 
} 
final CountDownLatch latch = new CountDownLatch(1); 
    public void countDown(){ 
    latch.countDown(); 
    } 

    public void await(){ 
    latch.await(); 
    } 
} 

concurrentActionQueue.add(new Action() { 
    @Override 
    public void execute() { 
     // will be executed from THREAD 2 
     HelperObject helperObj;// do something with object 

     helperObj.countDown(); 
    } 
} 
関連する問題