2015-09-22 17 views
5

Ho un metodo chiamato processOutbox. Voglio che sia thread sicuro. Non voglio che un altro thread chiami questo metodo mentre c'è un thread. L'ho implementato nel modo seguente. L'ho fatto correttamente? Ci sono delle lacune nella mia implementazione? Se ce ne sono, quindi si prega di consigli su come posso risolverlo.Come posso garantire la sicurezza dei thread nel seguente contesto?

this.start(); 
    outboxLock.lock(); 
    timer = new Timer(); 
    try{ 
    timer.scheduleAtFixedRate(new TimerTask() { 
      public void run() { 
       processOutbox(); 
      } 
     }, 0, period); 
    } finally{ 
     outboxLock.unlock(); 
    } 
+4

Hai bloccato solo la pianificazione. L'esecuzione non è ancora sicura. – Fildor

+0

Come faccio allora? Per favore consiglio – mayooran

+0

Suggerirei di sincronizzarlo sulla variabile statica di livello di classe. –

risposta

5

Se si desidera rendere il vostro metodo di processOutbox, è necessario utilizzare la parola chiave synchronized:

public class YourClass{ 
    public synchronized void processOutbox(){ 
     //do all you want 
    } 
} 

Maggiori informazioni su: https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

Se nel codice si dispone di un'istanza di YourClass chiamato ad esempio myInstance, tutte le chiamate a processOutbox() saranno thread-safe perché saranno bloccate a livello di istanza.

Ad esempio:

YourClass myInstance = new YourClass(); 
Thread thread1 = new Thread(){ 
    public void run(){ 
     myInstance.processOutbox(); 
    } 
    } 
Thread thread2 = new Thread(){ 
    public void run(){ 
     myInstance.processOutbox(); 
    } 
    } 
thread1.start(); 
thread2.start(); 

Qui thead2 sarà in attesa fino a quando Thread1 termina la chiamata a "processOutbox"

Ma per esempio:

YourClass myInstance = new YourClass(); 
YourClass myInstance2= new YourClass(); 
Thread thread1 = new Thread(){ 
    @Override 
    public void run(){ 
     myInstance.processOutbox(); 
    } 
}; 
Thread thread2 = new Thread(){ 
    @Override 
    public void run(){ 
     myInstance2.processOutbox(); 
    } 
} 
thread1.start(); 
thread2.start(); 

thead2 volontà NON attesa perché stanno chiamando il metodo su diverse istanze.

Qualcuno ha chiesto espressamente di usare ReentrantLock - Quindi sto aggiungendo quella risposta a questo, perché questo è corretto.

public class YourClass { 
    private Lock outboxLock = new ReentrantLock(); 
    public void processOutbox() { 
     outboxLock.lock() 
     try { 
      // do stuff 
     } finally { 
      outboxLock.unlock() 
     } 
    } 
} 

Dico questo in particolare perché si può anche fare le cose, dove si tengono gli altri thread dalla serratura senza causare loro di bloccare utilizzando tryLock invece.

public class YourClass { 
    private Lock outboxLock = new ReentrantLock(); 
    public void processOutbox() { 
     if(outboxLock.tryLock()) { 
      try { 
       // do stuff 
      } finally { 
       outboxLock.unlock() 
      } 
     } 
    } 
} 
+0

** Non voglio che un altro thread chiami questo metodo mentre è presente un thread. ** API Java –

+0

: "Quando un thread sta eseguendo un metodo sincronizzato per un oggetto, tutti gli altri thread che invocano metodi sincronizzati per lo stesso oggetto (sospendi l'esecuzione) fino a quando il primo thread non viene eseguito con l'oggetto. " –

+0

Come posso ottenere lo stesso usando il reentrantlock? per favore consiglio goku :) – mayooran