2009-04-30 13 views
10

JAVAのGUIで競合状態に対処していると思います。Javaの匿名クラスと同期と "this"

私はこのような匿名クラス内の「匿名メソッド」を作成、いくつかの方法があります:

synchronized foo() 
{ 
    someMethod(new TimerTask() 
    { 
      public synchronized run() 
      { 

       //stuff 

      } 
    }; 
} 

はQUESTION:そのrunメソッドがTimerTaskをオブジェクトまたはクラス上で同期さfooがであることを?

質問:run()宣言で "synchronized"を取り除き、run()本体の中にsynchronized(this){}ブロックがある場合、 "this"はTimerTaskオブジェクトを参照するか、 foo()を含むメソッドのインスタンスであるオブジェクトに?

ここから手伝ってください。

おかげで、 JBU

+0

これは、Java Concurrency In Practice(JCiP)の本にも表示される間違いです。それは、Javaが同期に関して非常に弱く型付けされているという同情です。 –

答えて

13

runメソッドは、TimerTaskで同期されています。同期されたinstance methods are always synchronized on thisオブジェクト。 (クラスメソッドはClassオブジェクト上で同期されます。)

あなたはfooがメンバーであるオブジェクトで同期したい場合は、qualify the this keyword.に必要foo()TimerTaskrun()メソッド内で、Barクラスのメンバであると仮定

public void run() { 
    synchronized(Bar.this) { 
    ... 
    } 
} 
+0

"同期メソッドは常にこのオブジェクトで同期されます。" - この場合、このオブジェクトはどのオブジェクトを区別するのが難しいですか。それは常に最も内側の/最も近いクラスですか? – jbu

+0

はい、私はあなたがそうすることができると思います。メソッドがメンバーであるインスタンスです。 run()は匿名のTimerTaskのメンバーです。 foo()は、囲むインスタンスのメンバーです。 – erickson

+0

BGGAをクローズすると面白いでしょう。これは従来の(制限された)クロージャの内部クラスを参照しますが、BGGA(より完全な)クロージャの外部クラスを参照します。 –

2

は、私はこれらの答えのかなり確信しているが、私は良いソースの気圧を掘ることができません。

最初の質問:
は、TimerTaskをロックします。

第2質問:
これはTimerTaskを指します。含まれているオブジェクトをロックしたい場合は、MyContainingObjectを使用します。

1

スイング要素にアクセスできるスレッドは1つだけです。それはAWT-EventQueue-0です。あなたはこれを知る必要があります。他のスレッドが溺れているか要素を変更している場合、GUIがクラッシュする可能性は非常に高いです。

 
    try { 
      SwingUtilities.invokeAndWait(new Runnable(){ 
       public void run(){ 
        Swing_Prozor1 prozor = new Swing_Prozor1(); 
       } 
      }); 
     } catch (InterruptedException e) { 
      //namjerno zanemareno 
     } catch (InvocationTargetException e) { 
      //namjerno zanemareno 
     } 

を、あなたがanonymusクラスを持っている場合、これはあなたがされたクラスのインスタンスを与えるので、あなたはanonymusクラスでこれをwritteingしている場合:このスレッドを使用してGUIを実行するには 。そのクラスのインスタンスです。

ClassName.this

うーん、あなたが書いたこの上記のコードは私にこのことを伝えます:クラスのインスタンスを取得するには、書き込みをしたいです。あなたはコードの一部を二度保護しました。 シンクロナイズドメソッドを記述すると、一度に1つのスレッドだけがこのメソッドにアクセスできることを意味します。他のスレッドは、同期化されたメソッドのロックが解除されている間待機します。

0

あなたがfooを同期させるために探している場合は()、実行()、あなたが

最終オブジェクトロック=新しいオブジェクト(のような明示的なロックオブジェクトを作成する場合があります)。

と同期してください。

foo() { 
    synchronized(lock) { 
     someMethod(new TimerTask() { 
      public void run() { 
       synchronized(lock) { 
        //stuff 
       } 
      } 
     } 
関連する問題