2009-04-30 22 views
10

Mi trovo in una condizione di gara, credo, nella mia GUI JAVA.classi java anonime e sincronizzazione e "questo"

Ho alcuni metodi che creano un "metodo anonimo" all'interno di una classe anonima come questa:

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

       //stuff 

      } 
    }; 
} 

domanda: che metodo run sincronizzato sull'oggetto TimerTask o la classe che foo è in?

question2: se mi sono liberato del "sincronizzato" nella dichiarazione di run(), e invece hanno una (questo) {} blocco sincronizzato all'interno del) corpo (pista, sarebbe "questo" fare riferimento all'oggetto TimerTask o all'oggetto che è un'istanza del metodo che contiene foo()?

Per favore aiutatemi qui.

Grazie, JBU

+0

Questo è un errore che appare anche nel libro Concurrency In Practice (JCiP) di Java. È un peccato che Java sia così debolmente tipizzato rispetto alla sincronizzazione. –

risposta

13

Il metodo run è sincronizzato sullo stesso TimerTask. Oggetto sincronizzato instance methods are always synchronized on this. (I metodi di classe sono sincronizzati sull'oggetto Class.)

Se si desidera sincronizzare il cui oggetto foo è membro, è necessario qualify the this keyword. Supponiamo foo() è un membro della classe Bar, all'interno del metodo di TimerTaskrun() , è possibile utilizzare

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

"I metodi sincronizzati sono sempre sincronizzati su questo oggetto." -È difficile distinguere quale oggetto sia QUESTO in questo caso. È sempre solo la classe più interna/più vicina? – jbu

+0

Sì, penso che potresti metterlo in questo modo. È l'istanza di cui il metodo è membro. run() è un membro del TimerTask anonimo; foo() è un membro dell'istanza che lo include. – erickson

+0

Sarebbe più divertente se avessimo delle chiusure BGGA. ciò si riferirebbe alla classe interna nelle chiusure tradizionali (limitate), ma alla classe esterna nelle chiusure BGGA (più complete). –

2

sono abbastanza sicuro di queste risposte, ma non riesco a scavare una buona fonte atm.

La prima domanda:
sincronizzata si bloccherà sul TimerTask.

Seconda domanda:
si riferisce al TimerTask; se si desidera bloccare l'oggetto contenitore, utilizzare MyContainingObject.this

1

C'è solo un thread che può avere accesso agli elementi swing. Questo è AWT-EventQueue-0. Devi essere consapevole di questo. Se altri tuoi thread sono drowing o elementi di cambiamento, c'è una buona probabilità che il gui si blocchi. per eseguire la vostra gui con questa discussione:

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

e se si dispone di classi via anonima questo vi darà istanza della classe in cui si è, quindi se siete in classe writteing Anonymus questo. è l'istanza di quella classe. Per ottenere un'istanza della classe che si desidera scrivere:

ClassName.this

hmm questo codice di cui sopra che hai scritto mi dice questo. Hai preteso una parte del codice due volte. Quando si scrive il metodo syncronized significa che solo un thread può accedere a questo metodo in una volta. Gli altri thread rimangono in attesa mentre il metodo syncronized è sbloccato.

0

Se siete alla ricerca per la sincronizzazione del foo() e run() allora si può creare un oggetto di blocco esplicito come

finale blocco Object = new Object();

e quindi sincronizzarsi su di esso.

foo() { 
    synchronized(lock) { 
     someMethod(new TimerTask() { 
      public void run() { 
       synchronized(lock) { 
        //stuff 
       } 
      } 
     }