Problema com uma thread

Olá!

Estou com um problema com uma thread minha. Não enxergo o problema e gostaria que alguém me desse uma luz.

public interface ProdutorConsumidor 
{
	public void setValor(int posicao, int valor);
	
}
public class Produtor implements Callable<Integer> 
{
	SharedBuffer sharedBuffer;
	private static Random r = new Random();
	
	public Produtor(SharedBuffer sharedBuffer)
	{
		this.sharedBuffer = sharedBuffer;
	}
	
	public Integer call() throws Exception 
	{
		System.out.printf("%-40s%s\t\t%s\n%-40s%s\n\n", "Posição", "Vetor", "Valor",
				"---------", "------\t\t-------");
		
		for(int posicao = 0; posicao < 100; posicao++ )
		{
			sharedBuffer.setValor(posicao, r.nextInt(100));
		}		
		
		return 1;
	}
}
public class SharedBuffer implements ProdutorConsumidor 
{	
	public static final int tamanhoBuffer = 10;
	public static int buffer [] = new int[tamanhoBuffer];
		
	public void setValor(int posicao, int valor) 
	{
		synchronized(this)
		{
			buffer[posicao%tamanhoBuffer] = valor;
			
			System.out.printf("%-40s%s\t\t%s\n%-40s%s\n\n", posicao, posicao%tamanhoBuffer, valor);
		}
	}
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

public class SharedBufferMain
{
	public static void main(String[] args)
	{
		ExecutorService executorService = Executors.newCachedThreadPool();
		
		SharedBuffer sharedBuffer = new SharedBuffer();
		
		FutureTask<Integer> futureTask1 = new FutureTask<Integer>(new Produtor(sharedBuffer));		
		
		executorService.execute(futureTask1);		
		
		executorService.shutdown();
	}
}

O que acontece: crio a thread na main e chamo Produtor. Quero fazer uma lista circular de 10 posições.
Em “call”, na classe Produtor, eu faço um loop de 100 vezes. O que acontece é que a thread entra no loop uma vez (classe sharedBuffer), imprime o que tem que imprimir e depois pára.

Ele deveria continuar por mais 99 vezes, mas não faz isso.

Pode ser um erro bobo meu, mas não vejo. Alguém faz o favor de me ajudar?
Estou treinando o uso de FutureTask, então, claramente, eu não precisaria usá-lo porque não quero retorno na call. Ignorem isso.

Obrigado.

ola amigo esse link ve se ajuda vc em algo.

[quote=uaslei Java]ola amigo esse link ve se ajuda vc em algo.

http://www.devmedia.com.br/articles/viewcomp.asp?comp=4459[/quote]

Obrigado pelo link…ajuda nunca é d+!

Mesmo assim, gostaria que alguém me ajudasse a enxergar erro no meu programa…

Me parece que o problema está no printf do método setValor. Troquei ele por System.out.println (“oi”); e então o método foi executado 100 vezes. Talvez algum erro na cadeia de formatação do printf.

É…por que será? Troquei por println e imprimiu 100x.

Os seus campos são inteiros, então vc deveria usar %d e não %s. Além disso, no printf o \n é %n

Mas estranho, não parecem ser esses os erros, até porque o printf costuma a disparar exceptions. Já tentou usar o depurador?

[quote=ViniGodoy]Os seus campos são inteiros, então vc deveria usar %d e não %s. Além disso, no printf o \n é %n

Mas estranho, não parecem ser esses os erros, até porque o printf costuma a disparar exceptions. Já tentou usar o depurador? [/quote]

É isso mesmo. A exceção não estava aparecendo pois o método estava sendo executado numa thread separada. Aliás, o método call “throws Exception”. Não me lembro onde ela vai parar.

Coloquei um try catch no método e vualá: “EFormat specifier ‘-40s’”.

[quote=ViniGodoy]Os seus campos são inteiros, então vc deveria usar %d e não %s. Além disso, no printf o \n é %n

Mas estranho, não parecem ser esses os erros, até porque o printf costuma a disparar exceptions. Já tentou usar o depurador? [/quote]

Tá jogando exceção…

MissingFormatArgumentException

IllegalArgumentException

Eu vou olhar a formatação e arrumá-la.

Obrigado pessoal pela ajuda!

Sim, pq tem bem mais parâmetros ali do que campos também. Era esse o problema.

Tem um problema ocorrendo quando eu chamo wait() no meu objeto. Eu descrevo o erro mais abaixo!

[code]
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

public class SharedBufferMain
{
public static void main(String[] args)
{
ExecutorService executorService = Executors.newCachedThreadPool();

	SharedBuffer sharedBuffer = new SharedBuffer();
	
	FutureTask<Integer> futureTask1 = new FutureTask<Integer>(new Produtor(sharedBuffer));
	FutureTask<Integer> futureTask2 = new FutureTask<Integer>(new Consumidor(sharedBuffer));
	
	executorService.execute(futureTask1);
	executorService.execute(futureTask2);
	
	executorService.shutdown();
}

}[/code]

[code]
import java.util.Random;
import java.util.concurrent.Callable;

public class Produtor implements Callable
{
SharedBuffer sharedBuffer;
private static Random r = new Random();

public Produtor(SharedBuffer sharedBuffer)
{
	this.sharedBuffer = sharedBuffer;
}

public Integer call() throws Exception 
{
	System.out.printf("%-40s%s\t\t%s\n%-40s%s\n\n", "Posição", "Vetor", "Valor",
			"---------", "------\t\t-------");
	
	for(int posicao = 0; posicao < 100; posicao++ )
	{
		sharedBuffer.setValor(posicao, r.nextInt(100));
	}		
	
	return 1;
}

}[/code]

import java.util.concurrent.Callable;

public class Consumidor implements Callable<Integer>
{	
	SharedBuffer sharedBuffer;
	
	public Consumidor(SharedBuffer sharedbuffer)
	{
		this.sharedBuffer = sharedBuffer;
	}
	
	public Integer call() throws Exception 
	{
		for(int posicao = 0; posicao < 100; posicao ++)
		{
			sharedBuffer.getValor(posicao);
		}
		
		return null;
	}
}
public interface ProdutorConsumidor 
{
	public void setValor(int posicao, int valor);
	public int getValor(int posicao);
}
public class SharedBuffer implements ProdutorConsumidor 
{	
	public static final int tamanhoBuffer = 10;
	public static int buffer [] = new int[tamanhoBuffer];
	public boolean turn;
	public int valor;
	
	public int getValor(int posicao)
	{
		synchronized(buffer)
		{		
			while(!turn)
			{
				try
				{
					buffer.wait();
				}
				
				catch(InterruptedException e)
				{
					e.printStackTrace();
				}	
			}

			valor = buffer[posicao%tamanhoBuffer];
			turn = false;
			buffer.notify();
			
			return valor;
		}
	}
	
	public void setValor(int posicao, int valor)
	{
		synchronized(buffer) 
		{
			while(turn)
			{
				try
				{
					buffer.wait();
				}
				
				catch(InterruptedException e)
				{
					e.printStackTrace();
				}
			}
			
			buffer[posicao%tamanhoBuffer] = valor;
			turn = true;
			buffer.notify();
			
			//System.out.printf("\n%s %d%d\n%s\n", posicao, posicao%tamanhoBuffer, valor);
			System.out.println(posicao+"                                         "+
					posicao%tamanhoBuffer+"               "+valor);
		}
	}
}

O que acontece é que, no segundo loop (posicao = 1) em Produtor ele verifica turn para ver de quem é a vez. Mesmo o produtor tendo o objeto do monitor, ele não pode produzir duas vezes (o intuito é produzir, consumir…sucessivamente no vetor circular). Quando ele tenta dar um wait() no objeto (buffer), aparece a exceção:

int[](Object).wait() line: 485 [local variables unavailable]
SharedBuffer.setValor(int, int) line: 16	
Produtor.call() line: 21
Produtor.call() line: 1	
FutureTask$Sync.innerRun() line: not available [local variables unavailable]	
FutureTask<V>.run() line: not available [local variables unavailable]	
ThreadPoolExecutor$Worker.runTask(Runnable) line: not available	
ThreadPoolExecutor$Worker.run() line: not available [local variables unavailable]	
Thread.run() line: not available [local variables unavailable]

Alguém poderia me fazer o favor de ajudar?
Não vejo erro em dar um wait no objeto, para que outra thread possa obter o objeto do monitor.