Baixo acoplamento processando grandes quantidades de dados

8

Geralmente, consigo um baixo acoplamento criando classes que trocam listas, conjuntos e mapas entre eles. Agora, estou desenvolvendo um aplicativo em lote Java e não consigo colocar todos os dados dentro de uma estrutura de dados porque não há memória suficiente. Eu tenho que ler e processar um pedaço de dados e depois passar para o próximo. Portanto, ter um baixo acoplamento é muito mais difícil, porque preciso verificar em algum lugar se ainda há dados para ler etc.

O que estou usando agora é:

Fonte -> Processo -> Persistir

As classes que processam precisam solicitar às classes Source se houver mais linhas para ler.

Quais são as melhores práticas e / ou padrões úteis nessas situações?

Espero estar me explicando, se não me disser.

Виталий Олегович
fonte
3
uma das formas de atingir baixo acoplamento é o de estabelecer um bom protocolo de comunicação entre as classes de origem e classes de processo
treecoder
3
Eu acho que você pode querer usar uma fila de mensagens - algum tipo de barramento de dados - para que suas classes coloquem as coisas em filas e as retirem das filas, em vez de interagir diretamente.
9788 Murph
@ Murph existe uma maneira simples ou uma boa biblioteca Java de usar uma fila de mensagens?
Виталий Олегович
@vitalik - Eu sou um desenvolvedor .NET e ainda sentindo o meu caminho com filas de mensagens geralmente não tão realmente em posição de fornecer uma resposta confiante (daí a minha resposta ser ao comentário)
Murph
1
@ Murph ok, obrigado de qualquer maneira! Acho que vou começar a estudar filas também!
Виталий Олегович

Respostas:

7

Pelos comentários, vejo que você está usando Java. Veja várias implementações da fila . Particularmente, BlockingQueue é útil para cenários produtor-consumidor . Você pode ter duas filas: uma entre Origem (produtor de dados) e Processo (consumidor de dados) e outra entre Processo (produtor de resultados) e Persistir (consumidor de resultados).

Com filas de bloqueio de capacidade limitada, é bastante fácil implementar sistemas eficientes (a parte do gargalo, seja o que for, é mantida alimentada com dados 100% do tempo), ainda usando apenas uma quantidade limitada de memória, independentemente da quantidade de dados disponíveis.

Joonas Pulakka
fonte
Sua solução é muito boa. Mas o que acontece se eu usar uma fila de capacidade limitada, e a fila estiver cheia e tentar adicionar algo a ela?
Виталий Олегович
@vitalik, você deve implementar uma estratégia, como armazenar temporariamente os dados em um banco de dados na memória ou em disco para outra solução.
Martijn Verburg
@MartijnVerburg sim, mas acho que seria mais fácil se houvesse a possibilidade de dormir o produtor até que haja mais espaço disponível na fila.
214126 #
1
@vitalik é claro que existe essa possibilidade (dormir um produtor), você apenas precisa fazê-lo. Algumas filas podem ser configuradas para serem bloqueadas, para que, se um produtor tentar inserir uma fila completa, você apenas bloqueie e efetivamente suspenda / gire (atente para qual) na fila para ter espaço.
Sdg
1
@vitalik: Veja, por exemplo, documentos BlockingQueue.put : insere o elemento especificado nessa fila, aguardando, se necessário, a disponibilidade de espaço. Simples e conveniente :)!
Joonas Pulakka
2

Uma fila de bloqueio (de Joonas Pulakka) é a resposta mais pesada. Uma resposta mais simples pode funcionar. Se você tiver todos os dados armazenados na fonte, basta passar uma referência ao processador, e ele pode simplesmente capturar os dados da fonte. Claro, isso é provavelmente o que você estava fazendo no passado. Você pode não ter todos os dados na memória na fonte e pode não obter o baixo acoplamento desejado.

O próximo passo seria usar uma interface do Enumerator ou Iterator. (Os iteradores são mais comuns em Java, embora na maioria das vezes esse removemétodo seja apenas um incômodo.) O processador obteria o iterador da fonte e depois os chamaria até o término. Se a fonte estiver obtendo terrabytes de dados de algum lugar, cada chamada poderá demorar um pouco. Mas se você estiver indo dormir o processador até que haja algo na fila de qualquer maneira, isso será feito automaticamente. E se a fonte ficar à frente do produtor, ela esperará automaticamente que o produtor ligue hasNexte next.

Se, por outro lado, você quer a fonte pegar dados a partir de sua fonte tão rápido quanto ele pode e estocando-o até que o processador alcança, não sentado à espera que o processador processo, então a fila - e threads-- múltipla comece a parecer uma boa ideia, se mais complicada. Agora, a fonte pode acumular os dados quando ele pode correr mais rápido (o seu limite sendo presumivelmente algo como disco I / O), e o processador pode reduzir o tamanho da pilha quando ele pode correr mais rápido, (seu limite sendo o quão rápido a persistência módulo pode persistir os dados).

RalphChapin
fonte