Conclusão sobre uma questão de Thread

E ai pessoal tudo bem? Bom eu fiz uns comentarios sobre uma questão sobre Thread que me deparei e gostaria de saber se estou certo ou errado, se estiver errado gostariam que me corrigissem.

Segue o cod:

[code]public class A {

synchronized void doTask1(){
	
	System.out.println(1);
	
	
}

}
[/code]


public class B extends Thread{

	A a;
	
	Thread t;
	
	B(A a, Thread t){
		
		this.a = a;
		
		this.t = t;
		
		
	}
	
	public void run(){
		
		doTask2();
				
	}
	
	public void doTask2(){
		
		synchronized (this.a) {
			
			try {
				
				t.join();
				
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
				
	}
	
	public void doTask3(){
		
		synchronized (this.a) {
			
			System.out.println(2);			
			
		}
		
	}
	
}

[code]
package exe24;

public class Teste {

public static void main(String[] args) throws InterruptedException {
	
	A a = new A();
	
	B b = new B(a, Thread.currentThread()); // é passado um objeto A e o Thread corrente Main.
	
	b.start();
	
	Thread.sleep(1000);
	
	a.doTask1();
	
	b.doTask3();
	
	
}

}[/code]

Quando “b” starta um thread ele executa seu método run() que por sua vez chama o método doTask2()
quando doTask2() é executado o Thread “b” obtém o bloqueio do objeto “a” e neste mesmo método doTask2()
a Thread corrente “b” se “anexa” ao ThreadMain contido em “t”. Então o ThreadMain continuando sua execução
entra em suspensão por 1 segundo devido ao sleep(1000), logo abaixo de Thread.sleep(1000) o ThreadMain tenta executar
a.doTask1() porém o Thread “b” esta anexado no ThreadMain devido ao join() usado em doTask2() sendo assim possui o bloqueio do objeto
"a" impedindo que o ThreadMain execute o método a.doTask1() e b.doTask3().

E entao nada vai ser compilado e isso nunca vai ter fim. Seria isso mesmo? To certou ou errado?

Uma coisa, o código compila independentemente de bloqueio ou não. Cara acho que vc errou por pouco, não é a thread “b” que se anexa a thread “main” é “main” que se anexa a thread “b”, vc chama join() na thread “main”. Então quando você chama t.join(); “main” vai para ser executado no final da thread “b”, a execução de “b” termina então a thread “main” segue normalmente, o resto do código é todo na “main”.

Espero ter ajudado.

Falow.

[quote=Rapapel]Uma coisa, o código compila independentemente de bloqueio ou não. Cara acho que vc errou por pouco, não é a thread “b” que se anexa a thread “main” é “main” que se anexa a thread “b”, vc chama join() na thread “main”. Então quando você chama t.join(); “main” vai para ser executado no final da thread “b”, a execução de “b” termina então a thread “main” segue normalmente, o resto do código é todo na “main”.

Espero ter ajudado.

Falow.[/quote]

Que compila eu sei. Agora o t.join() esta sendo executado é no meu “Thread b” não no “Main”.

Sim, seu join() faz b esperar pelo main, segurando a.
E seu doTask3() faz main esperar por a. Que nunca será liberado por B.

Um caso clássico de deadlock. Rode isso pelo console do java e, quando o sistema travar, pressione CTRL+BREAK. Você vai ver a VM indicando o deadlock.

[quote=ViniGodoy]Sim, seu join() faz b esperar pelo main, segurando a.
E seu doTask3() faz main esperar por a. Que nunca será liberado por B.

Um caso clássico de deadlock. Rode isso pelo console do java e, quando o sistema travar, pressione CTRL+BREAK. Você vai ver a VM indicando o deadlock.[/quote]

Opa, entao o que eu falei tava correto né, como faço pra rodar pelo console pra ver o deadlock? No mais muito obrigado Vini!!

Você não sabe executar seu programa com linha de comando?

Entra no prompt de comando. Vá até a pasta onde está o arquivo Teste.class e rode:

java -cp . exe24.Teste

Aí vc vai ver o sistema começar e travar. Quando isso ocorrer, aperte CTRL+Break

[quote=ViniGodoy]Você não sabe executar seu programa com linha de comando?

Entra no prompt de comando. Vá até a pasta onde está o arquivo Teste.class e rode:

java -cp . exe24.Teste

Aí vc vai ver o sistema começar e travar. Quando isso ocorrer, aperte CTRL+Break

[/quote]

LOL kkk nao tinha entendido quando vc falou “console do java”, no cmd sei sim hehe. Vlw!!

Agora pra nao precisar abrir um novo topico Vini deixa eu perguntar. Eu to com dificuldade em entender o uso do -cp(classpath) igual vc mesmo mostrou ai:

Qual a diferença se eu fizer:

java Teste // Aqui eu sei que a VM vai procurar por Teste.class.

No comando que vc mostrou o “.” logo apos o “cp” indica que a VM vai procurar dentro do diretorio “corrente(atual)” meu Teste.class, pra que o nome do pacote nesse caso o “exe24.Teste” igual vc fez?

[quote=evertonsilvagomesjava]

Qual a diferença se eu fizer:

Não vai funcionar por 2 motivos:

a) O Java não sabe seu CLASSPATH (especificado com “-cp .” ) e não sabe onde procurar sua classe Teste
b) Toda classe, ao ser chamada pela linha de comando com o programa java.exe, deve ser especificada com seu nome completo (ou seja, pacote + nome da classe).

Você sabe muito bem que o Java até poderia relevar tais coisas (procurar no seu computador a tal classe, e também aceitar só o nome da classe sem o pacote). Não é impossível fazer isso - você sabe que poucas coisas são impossíveis. Mas o Java requer que você especifique essas duas coisas por dois bons motivos:
a) Segurança - porque você precisa saber de onde ele está pegando a classe, e
b) Velocidade - se o Java tivesse de procurar alguma coisa, seria ainda mais lento que ele já é.

[quote=entanglement][quote=evertonsilvagomesjava]

Qual a diferença se eu fizer:

Não vai funcionar por 2 motivos:

a) O Java não sabe seu CLASSPATH (especificado com “-cp .” ) e não sabe onde procurar sua classe Teste
b) Toda classe, ao ser chamada pela linha de comando com o programa java.exe, deve ser especificada com seu nome completo (ou seja, pacote + nome da classe).

Você sabe muito bem que o Java até poderia relevar tais coisas (procurar no seu computador a tal classe, e também aceitar só o nome da classe sem o pacote). Não é impossível fazer isso - você sabe que poucas coisas são impossíveis. Mas o Java requer que você especifique essas duas coisas por dois bons motivos:
a) Segurança - porque você precisa saber de onde ele está pegando a classe, e
b) Velocidade - se o Java tivesse de procurar alguma coisa, seria ainda mais lento que ele já é.
[/quote]

Então entanglement o que estou confuso é pelo seguinte digamos q eu tenho o arquivo: Teste.java
no caminho: C:\teste

No prompt ja estou dentro dessa pasta teste e digito: javac Teste.java.

O compilador java vai gerar pra mim um .class Teste.class.

Então no prompt novamente dentro da pasta teste eu digito: java Teste.

Executa normal pra que vou precisar usar -cp entao? Isso q nao to entendendo =/.

Se você não especificar o -cp o java irá procurar nos classpaths especificados na variável de ambiente JAVA_CLASSPATH.
Se você essa variável não contiver nenhum valor, o comando java não funciona a menos que você coloque o -cp .

Dá uma lida nesse artigo, vai te ajudar: http://www.guj.com.br/article.show.logic?id=108

[quote=ViniGodoy]Se você não especificar o -cp o java irá procurar nos classpaths especificados na variável de ambiente JAVA_CLASSPATH.
Se você essa variável não contiver nenhum valor, o comando java não funciona a menos que você coloque o -cp .

Dá uma lida nesse artigo, vai te ajudar: http://www.guj.com.br/article.show.logic?id=108[/quote]

Li o artigo Vini porém a duvida ainda continua :cry:, pq aqui eu estou compilando e executando os arquivos da seguinte forma e esta funcionando normal…

Minha variavel Path ta configurada da seguinte maneira:

C:\Arquivos de programas\Java\jdk1.6.0_14\bin

Não é a PATH. É a JAVA_CLASSPATH

Omg, nao tenho essa variavel JAVA_CLASSPATH, eu li um artigo do Camilo: http://camilolopes.wordpress.com/2008/03/27/instal...em-ambiente-windows-5-minutes/
para configurar a variavel Path e Java_HOME.

Não é a mesma coisa?

Na verdade, a variável chama-se só CLASSPATH, sorry, eu confundi.
Curioso, estar funcionando. De qualquer forma, conseguiu ver o deadlock com o CTRL+BREAK?

Enfim, o -cp permite que você especifique o classpath. É necessário também se você tiver outros .jar no seu classpath. É com ele que você diz as bibliotecas que sua aplicação depende.

[quote=ViniGodoy]Na verdade, a variável chama-se só CLASSPATH, sorry, eu confundi.
Curioso, estar funcionando. De qualquer forma, conseguiu ver o deadlock com o CTRL+BREAK?

Enfim, o -cp permite que você especifique o classpath. É necessário também se você tiver outros .jar no seu classpath. É com ele que você diz as bibliotecas que sua aplicação depende.[/quote]

Ta dando erro quando tento compilar e executar =/, acho que é por causa do classpath mesmo, pq dentro do meu arquivo Teste.java tem objetos de outros arquivos, por isso ta dando erro na hora de compilar pelo prompt.

O caminho do arquivo Teste.java ta aqui:

C:\Users\everton\workspace\ExamLab\src\exe24\Teste.java

tentei fazer:

javac Teste.java

pra depois rodar o .class

Quando eu tenho uma classe sem usar outros objetos ou imports so com o método “main” e um System.out.println(“alguma coisa”) eu consigo rodar so com javac e java.


[quote=evertonsilvagomesjava][quote=Rapapel]Uma coisa, o código compila independentemente de bloqueio ou não. Cara acho que vc errou por pouco, não é a thread “b” que se anexa a thread “main” é “main” que se anexa a thread “b”, vc chama join() na thread “main”. Então quando você chama t.join(); “main” vai para ser executado no final da thread “b”, a execução de “b” termina então a thread “main” segue normalmente, o resto do código é todo na “main”.

Espero ter ajudado.

Falow.[/quote]

Que compila eu sei. Agora o t.join() esta sendo executado é no meu “Thread b” não no “Main”.[/quote]
É verdade: t.join() faz a thread corrente “b” se anexar ao final da thread t “main” e não ao contrário como eu disse antes, e como “b” esta com o bloqueio do objeto “main” vai ficar esperando, deadlock!!!

Boa sorte.