Problema curioso

Estou com um problema um tanto curioso…

A intencao:
Estava testando uma maneira de selecionar apenas os nomes que comecam com tal letra e mostra-los na coluna correspondente a essa letra.
Ex:
Nomes: Jose, Maria, Amanda, Denise, Geraldo, Ronaldo,etc…
Jose comeca com J então iria para a coluna de J
Maria comeca com M então iria para a coluna de M…e assim por diante.

O codigo:

for(x = 0; x < nomes.length; x++){
	for(y = 0; y < alfabeto.length; y++){
		if(nomes[x].startsWith(String.valueOf(alfabeto[y]), 0)){
			System.out.printf("|%c = %s\n", alfabeto[y], nomes[x]);
	}
}

O problema:
Se eu debugar essa parte do programa, no console da debugacao aparece a saida de printf.
Porem, se eu rodar o programar normalmente a saida de printf nao aparece.
Qual seria o motivo do console nao estar mostrando a saida quando rodo normalmente?

A saida:
Debugando:

MENU PRINCIPAL:
Selecione uma opção:
1-Inserir novo nome
2-Visualizar nomes
3-Editar um nome
4-Excluir um nome
5-Sair
2
|A = Amanda
|J = Jose
|M = Maria
MENU PRINCIPAL:
Selecione uma opção:
1-Inserir novo nome
2-Visualizar nomes
3-Editar um nome
4-Excluir um nome
5-Sair

Rodando Normalmente:

MENU PRINCIPAL:
Selecione uma opção:
1-Inserir novo nome
2-Visualizar nomes
3-Editar um nome
4-Excluir um nome
5-Sair
2
MENU PRINCIPAL:
Selecione uma opção:
1-Inserir novo nome
2-Visualizar nomes
3-Editar um nome
4-Excluir um nome
5-Sair

Já tive um caso, na época era um aplicativo em Applet, que era necessário dá um Thread.Sleep para poder executar corretamente, pois caso contrário, a execução era tão rápida que parecia que pulava o trecho de código, ou não era executado…
Também achei estranho na época e não achei solução para o problema, mas foi a solução que encontrei.

Tenta dá um Thread.Sleep(2000) e ve se solucionou o problema quando roda normalmente.

Como é que estás a ler do teclado as opção escolhida?

[quote=rsantik]Já tive um caso, na época era um aplicativo em Applet, que era necessário dá um Thread.Sleep para poder executar corretamente, pois caso contrário, a execução era tão rápida que parecia que pulava o trecho de código, ou não era executado…
Também achei estranho na época e não achei solução para o problema, mas foi a solução que encontrei.

Tenta dá um Thread.Sleep(2000) e ve se solucionou o problema quando roda normalmente.[/quote]

Fiz o que foi sugerido, porem a saida perdeu a formatacao e alem disso para que o proximo nome apareca eu tenho que apertar Enter.

O codigo

for(x = 0; x < nomes.length; x++){
	for(y = 0; y < alfabeto.length; y++){
			if(nomes[x].startsWith(String.valueOf(alfabeto[y]), 0)){
				System.out.printf("|%c = %s\n", alfabeto[y], nomes[x]);
					try {
					    Thread.sleep(2000);
					} catch (InterruptedException e) {
					    e.printStackTrace();
					}
				}
			}

A saida com Thread.sleep(2000);

MENU PRINCIPAL:
Selecione uma opção:
1-Inserir novo nome
2-Visualizar nomes
3-Editar um nome
4-Excluir um nome
5-Sair
2
|J = Joao

|J = Jose


|M = Maria


MENU PRINCIPAL:
Selecione uma opção:
1-Inserir novo nome
2-Visualizar nomes
3-Editar um nome
4-Excluir um nome
5-Sair

[quote=pmlm]
Como é que estás a ler do teclado as opção escolhida?[/quote]

Estou usando o Scanner.

[quote=Johnnny8]
Estou usando o Scanner.[/quote]

Que método do Scanner? Para ler da consola apenas deves usar o nextLine();

[quote=pmlm][quote=Johnnny8]
Estou usando o Scanner.[/quote]

Que método do Scanner? Para ler da consola apenas deves usar o nextLine();[/quote]

No meu projeto usei os seguintes metodos do Scanner:

nextByte();
nextLine();

Na realidade o meu problema nao e com a entrada de dados, e na saida de dados.
Da uma olhada no primeiro post de novo.
=]

Nunca desprezes uma hipótese, por ridícula que pareça…

Nao desprezei a sua hipotese…
Se pareceu que desprezei…Me desculpe, nao foi minha intencao, mas ja conferi as entradas na debugacao.
Os valores estao corretos e o Scanner esta funcionando.
O problema e na hora de monstrar a saida no console.

Nao desprezei a sua hipotese…
Se pareceu que desprezei…Me desculpe, nao foi minha intencao, mas ja conferi as entradas na debugacao.
Os valores estao corretos e o Scanner esta funcionando.
O problema e na hora de monstrar a saida no console.[/quote]

johnnny8 faça o que o pmlm disse use nextLine() o ponteiro fica preso quando se usa outros next***

se quer pegar um double faça: Double.parseDouble(scanner.nextLine());

byte a mesma coisa…

teste ai por favor.

Nao desprezei a sua hipotese…
Se pareceu que desprezei…Me desculpe, nao foi minha intencao, mas ja conferi as entradas na debugacao.
Os valores estao corretos e o Scanner esta funcionando.
O problema e na hora de monstrar a saida no console.[/quote]

johnnny8 faça o que o pmlm disse use nextLine() o ponteiro fica preso quando se usa outros next***

se quer pegar um double faça: Double.parseDouble(scanner.nextLine());

byte a mesma coisa…

teste ai por favor.

[/quote]

pmlm, a minha intencao nao era parecer que desprezei a sua hipotese. Se pareceu, venho novamente lhe pedir desculpa.
Estava equivocado porque na debugacao funcionava tudo.

douglasKd,
Testei aqui e funcionou!
Porem a minha duvida permanece…
Porque na debugacao tinha rodado tudo perfeitamente bem e na hora de rodar normalmente o metodo do Scanner deu problema?

O codigo:

menu = Byte.parseByte(input.nextLine());

Chuto eu que os bytes estão indo para algum buffer, dessa forma, como o processo de debug possui pausas, dá tempo do buffer despachar o que precisa ser printado.

Veja se adicionando a linha abaixo do printf, resolve o problema:

System.out.flush();

Ou tenta usar o

System.out.println();

pois nunca tive esse tipo de problema com ele.

Nao desprezei a sua hipotese…
Se pareceu que desprezei…Me desculpe, nao foi minha intencao, mas ja conferi as entradas na debugacao.
Os valores estao corretos e o Scanner esta funcionando.
O problema e na hora de monstrar a saida no console.[/quote]

johnnny8 faça o que o pmlm disse use nextLine() o ponteiro fica preso quando se usa outros next***

se quer pegar um double faça: Double.parseDouble(scanner.nextLine());

byte a mesma coisa…

teste ai por favor.

[/quote]

pmlm, a minha intencao nao era parecer que desprezei a sua hipotese. Se pareceu, venho novamente lhe pedir desculpa.
Estava equivocado porque na debugacao funcionava tudo.

douglasKd,
Testei aqui e funcionou!
Porem a minha duvida permanece…
Porque na debugacao tinha rodado tudo perfeitamente bem e na hora de rodar normalmente o metodo do Scanner deu problema?

O codigo:

menu = Byte.parseByte(input.nextLine()); [/quote]

a verdade é que esses métodos ai nextbyte, nextint, next***, só servem para ler Streams… para ler entradas do teclado sempre da problema.

Depois da execução do seu código tem o System.exit(0) ?

Se estiver, retire-o e tente executar novamente…

Se o resultado aparecer mesmo que depois, o motivo aí é porque vc está matando o sistema e interrompendo a thread…

Como não fala nada na API do Java, pode ser que o printf não seja Thread Safe, isso explicaria o comportamento estranho.

Tenta colocando o objeto System.out como synchronized

synchronized (System.out) {
    for(x = 0; x < nomes.length; x++)
        for(y = 0; y < alfabeto.length; y++)
            if(nomes[x].startsWith(String.valueOf(alfabeto[y]), 0))
                System.out.printf("|%c = %s\n", alfabeto[y], nomes[x]); 
}

Um abraço!

[quote=regis_hideki]Chuto eu que os bytes estão indo para algum buffer, dessa forma, como o processo de debug possui pausas, dá tempo do buffer despachar o que precisa ser printado.
[/quote]
regis_hideki,
Não sei afirmar se os bytes vão para um buffer. Porém fiz alguns testes em relacao ao tempo que o “buffer” demora pra despachar.

O teste:
Necessário saber:
O meu codigo foi escrito para selecionar apenas os nomes que comecam com tal letra e mostra-los na coluna correspondente a essa letra. Como foi dito no primeiro post.
Para fazer a declaracao dos nomes declarei um vetor nomes com 26 posicoes. São 26 posicoes porque no alfabeto portugues brasileiro tem essa quantia de letras.
A selecao dos nomes de acordo com as letras e feita no codigo abaixo.
Objetivo:
Medir o tempo que a JVM demora para comparar e imprimir no console as saidas determinadas.
Como foi feito:
Nesse codigo incorporei a funcao System.nanoTime para medir o tempo e descobrir o tempo que a JVM demora para fazer a comparacao e imprimir no console a letra inicial da String e o nome correspondente.
Importante saber:
Como o codigo vai comparar cada String com cada letra do alfabeto, devemos saber que um nome que comece com a letra A vai demorar menos tempo para ser processado pela JVM do que um nome que comece com Z.
Assim, segue o codigo e sua saida:

O codigo:

	for(x = 0; x < nomes.length; x++){
				for(y = 0; y < alfabeto.length; y++){
					if(nomes[x].startsWith(String.valueOf(alfabeto[y]), 0)){
					    long time0 = System.nanoTime();
					System.out.printf("|%c = %s\t", alfabeto[y], nomes[x]);
					long timeF = System.nanoTime();
					long variationTime = timeF - time0;
					System.out.print(variationTime + "ns\n");
				}
				}

As Saidas em nano segundos

|A = A	1601024ns
|B = B	114847ns
|C = C	108005ns
|D = D	108005ns
|E = E	108494ns
|F = F	108983ns
|G = G	121200ns
|H = H	109471ns
|I = I	108005ns
|J = J	108494ns
|K = K	108495ns
|L = L	111426ns
|M = M	108495ns
|N = N	110449ns
|O = O	108494ns
|P = P	107517ns
|Q = Q	109960ns
|R = R	111916ns
|S = S	109961ns
|T = T	111915ns
|U = U	109961ns
|V = V	109472ns
|W = W	108983ns
|X = X	110449ns
|Y = Y	109960ns
|Z = Z	110938ns
[/code][code]
|A = Alice	192064ns
|B = Bruna	151012ns
|C = Carlos	185711ns
|D = Daniela	155411ns
|E = Erika	151012ns
|F = Fabiano	149057ns
|G = Gustavo	144171ns
|H = Hermes	152967ns
|I = Italo	144659ns
|J = Joao	143192ns
|K = Katia	143682ns
|L = Laura	144659ns
|M = Mariana	146125ns
|N = Nara	144170ns
|O = Otavio	143682ns
|P = Patricia	143192ns
|Q = Quércia	143193ns
|R = Romario	144170ns
|S = Sara	146614ns
|T = Tulio	207703ns
|U = Uiara	150034ns
|V = Victoria	143681ns
|W = Walda	144171ns
|X = Xavier	189621ns
|Y = Yuri	151012ns
|Z = Zed	142705ns

Conclusão:
Se houver realmente um tempo para o “buffer” despachar alguma coisa para o console, este tempo para saidas curtas esta na faixa dos nano segundos.
Duvida em relacao ao teste:
Se o codigo foi escrito para pegar apenas a primeira letra do nome e comparar com o alfabeto. Porque na saida 2, quando declarei nomes a JVM demorou mais do que na saida1 quando declarei somente letras?

Tambem acho que printf pode não ser Thread Safe.
Porem, me surgiu uma duvida.
Qual a funcao do Syncronized e quando usa-lo?
Se este syncronized é para sincronizar duas acoes diferentes “”“thread”"" e suponhamos que printf e nao seja thread safe. Como poderia isso ocorrer de maneira “Safe” se printf nao foi feito para isso?

O synchronized serve para bloquear o objeto para a thread atual, deve-se tomar cuidado ao usar esse recurso pois isso impacta diretamente no desempenho, além de ter um risco de acontecer um “deadlock”.
No caso, se vc fizer como eu disse, o objeto System.out será bloqueado e só será liberado para os outros “prints” após o término daquele loop. Isso garante que tudo que tá dentro do synchronized seja impresso.

Para mais detalhes sobre o synchronized indico esses dois links:


http://www.guj.com.br/articles/43