ThreadsFundiuTicoETecoException

Caraca dei tilte numa parada sobre threads. Olhem esse código:

package avancado.threads;

import common.Console;

public class Threads {
	
	public static void main(String[] args) {
		
		Runnable geradorDeUm = new GeradorDeBits(true);
		Runnable geradorDeZero = new GeradorDeBits(false);
				
		Thread threadUm = new Thread(geradorDeUm);
		Thread threadZero = new Thread(geradorDeZero);		
		
		threadUm.start();
		threadZero.start();
	}

}

class GeradorDeBits implements Runnable {	
	private boolean bit;
	
	public GeradorDeBits(boolean bit) {	
		this.bit = bit;	
	}	
	
	public void run() { 
		for (int i = 0; i < 400; i++) {
			comeAlfafa();
			Console.prints(bit? 1 : 0);			
		}
	}	
	
	private void comeAlfafa(){
		for (int i = 0; i < 10000; i++)	
			Console.prints(""); 
	}
}

// Uma das saídas:
// 000000000000000000000000000111111111111111100000000000000000000000000000
// 000111111111000000000011111111111111111111110000000000001111111111100000
// 000000011111111111111111111111111110000011111111111111111111000000000000
// 011111111111111111100000000000111111111111111111111000000000001111111111
// 000000000000111111111111000000000011111111111111111111111000000000000011
// 111111111111111111111111111111111000000000000000000001111111111111111111
// 111100000000000011111111111111111111111000000000000000000000011111111111
// 000000000000000000000001111111111111111000000000000011111111111111110000
// 000000000000000000111111111111000000000000000000000000011111111111110000
// 000000001111111111111111111111111111000000000000000000000011111111111100
// 000000000111111111111111111111000000000000000000000000000000000000000000
// 00000000

Minha dúvida cruel é: quando eu começo as duas threads, e os zeros e uns não saem contínuos na tela, o que acontece?

A) A JVM fica alternando a execução das threads, como se fosse um “yield() involuntário”

C) As duas threads rodam “ao mesmo tempo” e a saída é resultado da “reação” do System.out (Console) às threads…

C) Ambas as respostas

D) Tá maluco rapá!

???

Outra dúvida: existe alguma objeção em eu sincronizar o Runnable.run(), ou isso não tem o menor sentido (estou em estado de tilte heheh)???

Quando você tem apenas um processador em sua máquina, e você está usando um sistema operacional que suporta threads nativamente (Windows, Solaris, Linux, AIX etc.) então o que ocorre é que o sistema operacional chaveia entre as threads em várias situações, entre as quais:

  • Quando o programa chama uma API do sistema operacional (“system call”), como é o caso de escrever algo no console. (A escrita em console é bufferizada parcialmente pelo sistema operacional e pelo Java, portanto é que você viu que não aparecem seqüências 010101010101 e sim 00000111111000000).
  • Quando transcorreu uma determinada fatia de tempo (time slice) e o sistema operacional julgar que é necessário transferir o controle a outra thread ou processo.
  • Os algoritmos para essa transferência de controle são um pouco complexos (embora ocupem normalmente só algumas centenas de linhas de código) e normalmente levam em conta prioridades de threads, de processos, se a thread solicitou uma chamada a API que “bloqueia” esperando, por exemplo, por uma leitura de disco ou de teclado etc.

Não, não faz muito sentido. O run() normalmente só é chamado por uma thread para aquele objeto, então o lock não vai adiantar nada.

A dica é: só use “synchronized” se souber muito bem o que está fazendo.
Em 99% dos casos, usar as novas classes de java.util.concurrent resolve seus problemas.
95% do tempo as pessoas usam “synchronized” por magia ou mistificação, ou porque ouviram falar que é bom para alguma coisa.

Então a resposta seria ‘A’? Ou seja, o que acontece na verdade é que esse “multithreading” na verdade é uma simples alternância de execução, como se fosse um yield() automático?

Não, não faz muito sentido. O run() normalmente só é chamado por uma thread para aquele objeto, então o lock não vai adiantar nada.[/quote]

Claro!!! O código que chama o run() não é multi-threaded a não ser que eu thredeie!!! Destravou! :smiley:

Então a resposta seria ‘A’? Ou seja, o que acontece na verdade é que esse “multithreading” na verdade é uma simples alternância de execução, como se fosse um yield() automático?[/quote]

Depende. Se você tiver mais de um processador, pode ser a B também.

Não, não faz muito sentido. O run() normalmente só é chamado por uma thread para aquele objeto, então o lock não vai adiantar nada.[/quote]

Claro!!! O código que chama o run() não é multi-threaded a não ser que eu thredeie!!! Destravou! :D[/quote]

Eu threadeio, tu threadeias, ele threadeia, nós threadeamos, vós threadeais, eles threadeiam.

Agora fale tudo isso comendo farinha. :smiley:

Edit: Ah sim, o run() é chamado pelo start() da thread, em sã consciência você não o chama diretamente.

[quote=thingol]A dica é: só use “synchronized” se souber muito bem o que está fazendo.
Em 99% dos casos, usar as novas classes de java.util.concurrent resolve seus problemas.
95% do tempo as pessoas usam “synchronized” por magia ou mistificação, ou porque ouviram falar que é bom para alguma coisa.[/quote]

Já tentei ler sobre concurrent mas é sinistro, pô tem um lance de uns wrappers de primitivos, uns métodos pra substituir operadores, <prepotente>achei escroto…</prepotente>

Sobre synchronized realmente é meio enigmático pra mim quando usar ou não, mas pelo menos é bom saber que se eu estiver em dúvida, provavelmente não preciso disso…

[quote=#@®®¡$]Eu threadeio, tu threadeias, ele threadeia, nós threadeamos, vós threadeais, eles threadeiam.

Agora fale tudo isso comendo farinha. :D[/quote]

Já tô rindo só de imaginar como é kkkkkkkkkkkkkkkk :lol:

Uêeeeeeeepa! Isoladamente como assim?

Leia a palestra do Sun Tech Days -

Untangling the Threads: Java Concurrency and Synchronization Utilities

  • você vai ver que fazer um servidor que recebe mensagens via sockets, com um pool de threads (um problema que não é trivial), é ridiculamente fácil com essas novas classes.

Se explicarem bem pra você vai ver que 95% dos problemas (mesmo os mais complicados) se resolvem com essas classes.

Os javadocs dessas classes são imensos, mas têm um monte de exemplos (que normalmente não existem nos javadocs das outras classes do java) e as classes são grandes porque o sr. Doug Lea, que escreveu praticamente sozinho o pacote, pensou em TUDO.

Uêeeeeeeepa! Isoladamente como assim? [/quote]

Eu disse “isoladamente”? Ih, foi mal, foi um daqueles momentos em que eu quero falar uma palavra e falo outra. Eu deveria ter dito “diretamente”, tanto que editei meu post e corrigi.

O run() existe para cumprir o contrato que Runnable propõe, que é a de rodar em uma thread separada, por isso você não chama o método diretamente. :wink:

Isso eu sei :wink: Valeu galera vou olhar o link do thingol, obrigado!