Jeśli chcesz, aby metoda swoją processOutbox, należy użyć słowa kluczowego synchronized
:
public class YourClass{
public synchronized void processOutbox(){
//do all you want
}
}
Więcej informacji na: https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
Jeśli w kodzie masz instancją YourClass nazywa na przykład myInstance
, wszystkie połączenia z processOutbox()
będą bezpieczne dla wątków, ponieważ będą zablokowane na poziomie instancji.
Na przykład:
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();
Tutaj thead2 będzie czekał aż thread1 kończy wezwanie do "processOutbox"
Ale na przykład:
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 będzie NIE czekać ponieważ oni wywołują metodę w różnych instancjach.
Ktoś specjalnie zapytał o używanie ReentrantLock - więc dodam tę odpowiedź do tego, ponieważ ta jest prawidłowa.
public class YourClass {
private Lock outboxLock = new ReentrantLock();
public void processOutbox() {
outboxLock.lock()
try {
// do stuff
} finally {
outboxLock.unlock()
}
}
}
Wspominam o tym specjalnie, ponieważ można też robić rzeczy, gdzie trzymasz innych wątków z zamka bez powodowania je zablokować za pomocą tryLock zamiast.
public class YourClass {
private Lock outboxLock = new ReentrantLock();
public void processOutbox() {
if(outboxLock.tryLock()) {
try {
// do stuff
} finally {
outboxLock.unlock()
}
}
}
}
Zamknąłeś tylko planowanie. Wykonanie nadal nie jest bezpieczne dla wątków. – Fildor
Jak mam to zrobić? Proszę o poradę. – mayooran
Proponuję zsynchronizować go na zmiennej statycznej na poziomie klasy. –