Olá, estou estudando Java faz algum tempo, é, estou em dúvida num método que vi o meu professor usar. O método Syncronized. Para que serve? Ficarei agradecido quem me ajudar!
synchronized
não é um método, é uma palavra-chave que pode ser aplicada a métodos. Ex:
// método sincronizado
public synchronized void fazAlgo() {
// faz algo...
}
// método não sincronizado
public void fazAlgo2() {
// faz algo...
}
A ideia é que um método sincronizado de um mesmo objeto não pode ser executado por 2 threads ao mesmo tempo. Para dar um exemplo, vamos supor que tenho essa classe:
public class Tarefa {
public void fazAlgo() {
System.out.println("fazendo algo...");
try {
// espera 2 segundos (para simular que está fazendo algo demorado)
Thread.sleep(2000);
} catch (InterruptedException ex) {}
System.out.println("fim");
}
}
Ela só imprime algumas mensagens, e fica 2 segundos parada (para simular alguma tarefa demorada). Agora vamos criar várias threads que chamam este método, para o mesmo objeto:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class SynchTest {
public static void main(String[] args) throws Exception {
// cria um pool de 5 threads
int qtdThreads = 5;
ExecutorService pool = Executors.newFixedThreadPool(qtdThreads);
// adiciona as threads no pool
Tarefa tarefa = new Tarefa();
for (int i = 0; i < qtdThreads; i++) {
pool.submit(() -> tarefa.fazAlgo());
}
// espera terminar
pool.awaitTermination(2 * qtdThreads, TimeUnit.SECONDS);
}
}
A saída será algo do tipo:
fazendo algo...
fazendo algo...
fazendo algo...
fazendo algo...
fazendo algo...
fim
fim
fim
fim
fim
Obs: pode ser que as saídas fiquem misturadas também (uma termine no meio, etc), já que threads não são determinísticas e a ordem não é garantida.
Isso acontece porque, enquanto uma das threads está no sleep
, outra thread pode começar a executar (mesmo que seja o mesmo método do mesmo objeto).
Agora se eu mudar o método fazAlgo
para ser sincronizado:
public class Tarefa {
// *** agora o método é synchronized ***
public synchronized void fazAlgo() {
System.out.println("fazendo algo...");
try {
// espera 2 segundos (para simular que está fazendo algo demorado)
Thread.sleep(2000);
} catch (InterruptedException ex) {
}
System.out.println("fim");
}
}
A saída será:
fazendo algo...
fim
fazendo algo...
fim
fazendo algo...
fim
fazendo algo...
fim
fazendo algo...
fim
Pois agora, como o método é sincronizado, só uma thread pode executá-lo por vez. Então todas as outras threads tem que esperar a thread atual terminar, para só depois chamar o método de novo.
Claro que o assunto (threads, sincronização, etc) é bem mais complexo que isso, e um bom ponto de partida é este tutorial.
CARA MUITO OBRIGADO, vc me salvou!