Ho uno scenario produttore-consumatore in cui i produttori producono molto più velocemente di quanto i consumatori possano consumare. In generale, la soluzione consiste nel bloccare i produttori poiché uno scenario produttore/consumatore funziona alla stessa velocità del componente più lento. La limitazione o il blocco dei produttori è non una buona soluzione perché la nostra applicazione offre abbastanza tempo per i consumatori di recuperare il ritardo.Implementazione Java "Queed Queue" per produttori veloci, consumatori lenti
Ecco un diagramma che rappresenta una "fase" pieno nella nostra applicazione contro uno scenario più comune:
Our Application Common Scenario
2N +--------+--------+
|PPPPPPPP|oooooooo| P = Producer
|PPPPPPPP|oooooooo| C = Consumer
N +--------+--------+ N +--------+--------+--------+ o = Other Work
|CPCPCPCP|CCCCCCCC| |CPCPCPCP|CPCPCPCP|oooooooo| N = number of tasks
|CPCPCPCP|CCCCCCCC| |CPCPCPCP|CPCPCPCP|oooooooo|
------------------- ----------------------------
0 T/2 T 0 T/2 T 3T/2
L'idea è quella di massimizzare il throughput non inibendo i produttori.
I dati su cui operano i nostri compiti sono facilmente serializzabili, quindi ho in programma di implementare una soluzione di filesystem per svuotare tutte le attività che non possono essere immediatamente soddisfatte.
Sto utilizzando Java ThreadPoolExecutor
con un BlockingQueue
con una capacità massima per garantire che non si esaurisca la memoria. Il problema è nell'implementare una tale coda "a livelli", in cui le attività che possono essere accodate in memoria vengono eseguite immediatamente, altrimenti i dati vengono accodati sul disco.
mi è venuta in mente due possibili soluzioni:
- implementare una
BlockingQueue
da zero, usando l'implementazioneLinkedBlockingQueue
oArrayBlockingQueue
come riferimento. Questo può essere semplice come copiare l'implementazione nella libreria standard e aggiungere la lettura/scrittura del filesystem. - continuare a utilizzare un
BlockingQueue
implementazione standard, attuare un separatoFilesystemQueue
per memorizzare i miei dati, e l'utilizzo di uno o più thread per annullare l'accodamento file, creareRunnable
s e accodare utilizzando ilThreadPoolExecutor
.
Sono entrambi ragionevoli e c'è un approccio migliore?