Dúvidas sobre threads (wait, notify e setPriority)

Olá Pessoal.

Estou na reta final dos estudos para o SCJP 6, que será nesta quarta-feira. Hoje eu concluí o livro e estou com uma série de dúvidas hehe. Vou citar as dúvidas, os exemplos que fiz, não funcionaram. Primeiro, testando o notify() e wait():

Classe ThreadB

[code]public class ThreadB extends Thread {

int total;

public void run() {
	synchronized (this) {
		for (int i = 0; i < 100; i++) {
			total += i;
		}

		notify();
	}
}

}[/code]

Classe ThreadA

[code]public class ThreadA {

public static void main(String[] args) {
	ThreadB b = new ThreadB();
	b.start();
	
	synchronized (b) {
		try {
			System.out.println("Esperando b completar...");
			b.wait();
		} catch (InterruptedException e) {}
		
		System.out.println("Total: " + b.total);
	}
}

}[/code]

Por que a classe trava em “Esperando b completar…”?? Não era para o notify() liberar o recurso?

A outra dúvida com thread, é na parte do setPriority, como é mostrado abaixo:

Classe Contador

[code]public class Contador implements Runnable {

public void run() {
	for (int i=0; i <= 100; i++) {
		System.out.print(i + " ");
	}
	
	System.out.println("");
	System.out.println(Thread.currentThread().getName());
	System.out.println("");
}

}[/code]

Classe TestePrioridade

[code]public class TestePrioridade {

public static void main(String[] args) {
	Contador c = new Contador();

	Thread t1 = new Thread(c, "Thread-1");
	t1.setPriority(Thread.MIN_PRIORITY);

	Thread t2 = new Thread(c, "Thread-2");
	t2.setPriority(Thread.MAX_PRIORITY);

	t1.start();
	t2.start();
}

}[/code]

A outra dúvida é… Se eu setei o t2 como prioridade máxima, ele não deveria executar primeiro que o t1?

Essas foram algumas dúvidas sobre threads que eu obtive ao estudar o livro. Se alguém puder me ajudar, ficarei muito grato.

Abraços.

  1. Não há nada em ThreadA e ThreadB que garanta que o notify() ocorra antes do wait. Se o notify ocorrer antes do wait, provavelmente o seu programa vai travar.

  2. Não confie em prioridade de Threads. O sistema operacional pode ignorá-las por completo se ele quiser. Além do mais, System.out.println é relativamente lento e tem gargalos de desempenho que podem fazer uma Thread esperar, pois ele precisa sincronizar internamente para garantir a consistência do texto escrito na saída.
    Elimine o System.out interno das suas Threads que daí as prioridades podem fazer mais sentido, se o sistema operacional quiser.

Ah, e poste este tipo de dúvida no fórum de certificação. Lá você conseguirá respostas melhores e mais rapidamente.

Hum, entendi sobre prioridade, eu vou fazer o teste depois.

Então, quanto ao notify(), se eu der o b.start() depois do bloco synchronized, vai funcionar?

[quote=Pilantra]Hum, entendi sobre prioridade, eu vou fazer o teste depois.

Então, quanto ao notify(), se eu der o b.start() depois do bloco synchronized, vai funcionar?[/quote]

Não. pois ele vai chegar no wait antes que a outra Thread comece. Como a outra Thread não começou, ela não vai poder dar notify.

Putz, então como resolveria isso? Meio complicado esse negócio do notify.

Quando você dá um wait, é porque teoricamente você está esperando acontecer alguma coisa. A documentação do método wait diz que é recomendado que ele seja colocado dentro de um while.while (coisaQueQueroQueAcontecaAindaNaoAconteceu) { obj.wait(); }Assim, você elimina dois problemas:

  1. O problema de o notify ocorrer antes, pois teoricamente você só dá o notify (ou notifyAll) depois que essa coisa aconteceu. Assim, se tiver alguém esperando essa coisa, esse alguém vai acordar. Se ninguém estiver esperando ainda, então nem vai esperar.

  2. As vezes o wait pode acordar de forma espúria (sem ser notificado). Em geral isso pode ocorrer se o sistema operacional não tiver um controle de thread bom, e para evitar isso, é recomendado usar aquele while, pois se o wait acordar de bobeira, ele volta a dormir.

Enfim, leia a documentação dos métodos wait, notify e notifyAll.

1 curtida

Valeu cara!! Ajudou muito.

Abraços!

embora se chame “wait” o método não serve para esperar. O metodo wait trava enquanto o notify não for dado.
( wait significa : espera o notify) . Use notifyAll em vez de notify. Isso e uma boa pratica de trabalho com threads.

Para executar um trabalho enquanto a outra thread corre e esperar por ela no fim use join() e não wait().

Não. O modelo de threads do java ( não tem nada a haver com OS) não garante nenhum tipo de ordem ao correr os threads.
A prioridade não significa que vai correr primeiro, significa que vai correr mais vezes.

No modelo de threads o tempo do porcessador é dividido pelo numero de threads presentes , pesado pelas suas prioidades.
Portanto, se todos tem a mesma prioridade, cada um ganha o mesmo tempo de execução por ciclo. Mas se a prioridade é maior ele ganha maior tempo por ciclo. Quanto tempo não é garantido, portanto, na realidade a prioridade pode ser ignorada.

Veja a priopridade como um dica para a JVM e não como uma obrigação da JVM.
Lembrar que o modelo de threads do java não tem nada a haver com o modelo de thread do OS nativo. A JVM pode converter Threads java em threads nativas, mas não é obrigada a isso. Normalmente a JVM não faz isso.
A separação é improtante, porque mesmo em OS que nao suportam multiprocesso é possivel ter uma JVM com threads (aliás essa é umas vantagens principais do modelo de threads da JVM)

1 curtida

Valeu sergiotaborda. Matou minha dúvida.

Abraços.