Alternativa a objetos estáticos

8 respostas
jks1903

Pessoal, necessito de uma opinião (e também orientações) sobre a melhor forma de solucionar meu problema.

Estou desenvolvendo uma aplicação que fará o uso de Threads, e essas acessarão um conjunto de dados inúmeras vezes durante sua execução, afim de verificar a existência ou não de determinada informação. Devido ao alto número de acessos, penso que acessar um BD toda vez possa comprometer o desempenho. Pensei então na possibilidade de ao início da aplicação carregar todos os dados em uma coleção (List por exemplo) e fazer as threads consultarem e persistirem dados nessa coleção. Aí ao final da execução das mesmas eu atualizaria o BD com os valores dessa lista.

O porém da situação é que todas as threads necessitam “ver” o mesmo objeto, ou seja, não é possível haver duas instâncias dessa lista numa mesma execução do programa. Pensei em usar um atributo estatico, o que acredito resolver meu problema. MAs pesquisando um pouco sobre o assunto, inclusive aqui no forum vi que o pessoal desencoraja o uso de metodos, atributos e etc que sejam estaticos.

Minha dúvida é, qual seria a melhor alternativa par atender essa minha necessidade?

Agradeço desde já.

8 Respostas

rmendes08

Já pensou em usar um framework de persistência ? Como o Hibernate por exemplo ? Pois isso que você descreveu é muito parecido com o que ele faz …

jks1903

Você refere-se ao recurso de cache do Hibernate?

Eu pretendo utilizar o Hibernate sim, porém desconhecia essa parte de configuração de cache (a qual ainda estou vendo melhor o funcionamento).
Mas uma dúvida que me surgiu, de repente voce possa me adiantar.

No meu caso cada Thread criada possui sua própria sessão com o banco, ou seja, se hoverem 5 threads haverão 5 sessões diferentes.
A cache (caso a sua sugestão seja o uso de cache mesmo) do Hibernate seria única para todas essas sessões ou cada sessão teria uma? Caso a cache não seja compartilhada entre as sessões, acredito que não poderei usar esse recurso.

Obrigado.

E

Um modo de fazer isso é o seguinte: o método que cria as threads também cria o tal objeto que deve ser visto por todas as threads, e passa esse objeto para a classe que representa a thread. Você vai ter um objeto só, mas ele não vai ser estático.

Uma vantagem de fazer isso é o seguinte: imagine que você precise criar várias instâncias da classe que cria as threads. Se o tal objeto compartilhado pelas threads fosse estático, você não poderia criar várias instâncias da classe que cria as threads :slight_smile:

rmendes08

Você refere-se ao recurso de cache do Hibernate?

Eu pretendo utilizar o Hibernate sim, porém desconhecia essa parte de configuração de cache (a qual ainda estou vendo melhor o funcionamento).
Mas uma dúvida que me surgiu, de repente voce possa me adiantar.

No meu caso cada Thread criada possui sua própria sessão com o banco, ou seja, se hoverem 5 threads haverão 5 sessões diferentes.
A cache (caso a sua sugestão seja o uso de cache mesmo) do Hibernate seria única para todas essas sessões ou cada sessão teria uma? Caso a cache não seja compartilhada entre as sessões, acredito que não poderei usar esse recurso.

Obrigado.

Para isso serve o cache de segundo nível, o cache de 1o nível é feito para cada sessão, o cache de 2o nível é feito em uma camada abaixo.

Mas imaginemos que você dispense o uso do Hibernate e faça na unha com JDBC. Na boa mesmo, eu vejo muito pouco ganho em manter uma lista compartilhada e sincronizada entre threads, pois no momento em que uma delas acessa a lista, você bloqueia as outras 4.

Você tem alguma idéia da razão entre leitura e escrita no BD que essas threads executarão ? Com base nisso é que podemos elaborar uma solução mais apropriada.

jks1903

entanglement:
jks1903:

O porém da situação é que todas as threads necessitam “ver” o mesmo objeto, ou seja, não é possível haver duas instâncias dessa lista numa mesma execução do programa. Pensei em usar um atributo estatico, o que acredito resolver meu problema. MAs pesquisando um pouco sobre o assunto, inclusive aqui no forum vi que o pessoal desencoraja o uso de metodos, atributos e etc que sejam estaticos.

Um modo de fazer isso é o seguinte: o método que cria as threads também cria o tal objeto que deve ser visto por todas as threads, e passa esse objeto para a classe que representa a thread. Você vai ter um objeto só, mas ele não vai ser estático.

Uma vantagem de fazer isso é o seguinte: imagine que você precise criar várias instâncias da classe que cria as threads. Se o tal objeto compartilhado pelas threads fosse estático, você não poderia criar várias instâncias da classe que cria as threads :)

Boa idéia.
Vou tentar isso e ficando tudo certo deixo o tópico como resolvido.

Obrigado.

jks1903

Você refere-se ao recurso de cache do Hibernate?

Eu pretendo utilizar o Hibernate sim, porém desconhecia essa parte de configuração de cache (a qual ainda estou vendo melhor o funcionamento).
Mas uma dúvida que me surgiu, de repente voce possa me adiantar.

No meu caso cada Thread criada possui sua própria sessão com o banco, ou seja, se hoverem 5 threads haverão 5 sessões diferentes.
A cache (caso a sua sugestão seja o uso de cache mesmo) do Hibernate seria única para todas essas sessões ou cada sessão teria uma? Caso a cache não seja compartilhada entre as sessões, acredito que não poderei usar esse recurso.

Obrigado.

Para isso serve o cache de segundo nível, o cache de 1o nível é feito para cada sessão, o cache de 2o nível é feito em uma camada abaixo.

Mas imaginemos que você dispense o uso do Hibernate e faça na unha com JDBC. Na boa mesmo, eu vejo muito pouco ganho em manter uma lista compartilhada e sincronizada entre threads, pois no momento em que uma delas acessa a lista, você bloqueia as outras 4.

Você tem alguma idéia da razão entre leitura e escrita no BD que essas threads executarão ? Com base nisso é que podemos elaborar uma solução mais apropriada.

Escrita ocorrerá esporadicamente, o que ocorre com extrema frequencia é a leitura dos dados. A aplicação no caso trabalha com um dicionário de palavras. O usuário digita ou carrega um arquivo texto e essas threads verificam se as palavras existem no dicionário. Estou usando threads para melhorar o desempenho, pois busco frase a frase e separo por palavras. Aí cada Thread analisa o que cada palavra é, se Verbo, Adjetivo e etc, tudo isso já consta no dicionário. E como esporadicamente aparecerá uma palavra nova, são raros os casos de escrita, mas podem ocorrer.

Vou testar a idéia que o entanglement sugeriu, acho que vai solucionar meu problema. Mas qualquer problema volto a postar, vlw pela ajuda.

E

Para estruturas de dados que precisam ser infrequentemente escritas e muito frequentemente lidas, use uma estrutura de dados não-bloqueante.

Por exemplo, veja :

http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html

douglaskd

cara vou te passar um código que talves possa abrir um pouco mais seu leque de opções:

public class Dicionario {

	BuscaAdjetivos bAdjetivos; // Callable
	BuscaVerbos bVerbos; // Callable
	BuscaSubstantivos bSubstantivos; // Callable

	public String Buscar(String Palavra) {

		String result = null;
		
		bAdjetivos = new BuscaAdjetivos(Palavra);
		bVerbos = new BuscaVerbos(Palavra);
		bSubstantivos = new BuscaSubstantivos(Palavra);

		ExecutorService executorService = Executors.newCachedThreadPool();

		Set<Callable<String>> buscadores = new HashSet<Callable<String>>();

		buscadores.add(bAdjetivos);
		buscadores.add(bSubstantivos);
		buscadores.add(bVerbos);

		try {
			System.out.println("Pesquisando...");
			result = executorService.invokeAny(buscadores);
		} catch (InterruptedException e) {

			e.printStackTrace();
		} catch (ExecutionException e) {

			e.printStackTrace();
		}finally{
			
			executorService.shutdown();
		}

		return result;

	}
}
public class BuscaAdjetivos implements Callable<String> {

	private String Palavra;

	public BuscaAdjetivos(String palavra) {
		this.Palavra = Palavra;
	}

	public void setPalavra(String Palavra) {

		this.Palavra = Palavra;
	}

	@Override
	public String call() throws Exception {

		Random gerador = new Random();
		int numero = gerador.nextInt(10000);

		Thread.sleep(numero);

		return "adjetivo";
	}

}
public class BuscaVerbos implements Callable<String> {

	private String Palavra;

	public BuscaVerbos(String palavra) {
		this.Palavra = Palavra;
	}

	public void setPalavra(String Palavra) {

		this.Palavra = Palavra;
	}

	@Override
	public String call() throws Exception {

		Random gerador = new Random();
		int numero = gerador.nextInt(10000);

		Thread.sleep(numero);

		return "Verbos";
	}

}
public class BuscaSubstantivos implements Callable<String> {

	private String Palavra;

	public BuscaSubstantivos(String palavra) {
		this.Palavra = Palavra;
	}

	public void setPalavra(String Palavra) {

		this.Palavra = Palavra;
	}

	@Override
	public String call() throws Exception {

		Random gerador = new Random();
		int numero = gerador.nextInt(10000);

		Thread.sleep(numero);

		return "Substantivos";
	}

}
public class testDicionario {

	public static void main(String[] args) {
		Dicionario dic = new Dicionario();

		System.out.println(dic.Buscar("adv"));
	}
}

olha que legal, o método executorService.invokeAny roda até que uma das 3 threads retorne um valor, quando ele retornar as outras são canceladas.

a questão da Base onde as palavras ficaram armazenadas, olha... para ser bem sincero. eu criaria 3 bases... que sejam listas, ou arquivos, para cada uma acessar individualmente.

veja se o código te exclarece algo...

Criado 8 de maio de 2013
Ultima resposta 8 de mai. de 2013
Respostas 8
Participantes 4