I will describe the application in full.
There is a group of threads - json handlers . they take json objects from the SynchronousQueue, which is called jsonQueue and process. There is a group of threads - generators of json-objects, which generates json and puts it in jsonQueue. To generate json generators, we need data that is loaded by a pool-loader. In the pool-loader, I submit a task (Runnable) that says - load me so much data for such an id. A json object consists of an id field and a value field. One id can correspond to a lot of value, but the json object itself contains only 1 id and 1 value.
Handlers work like this: while (true) {take an object from a jsonQueue and process it}
Generators work like this: while (true) {generate a json object and shove it in jsonQueue}
That is, for 1 iteration the flow generator generates 1 object in which there is 1 id and 1 value and shoves in jsonQueue.
In order that each time a flow generator tries to generate an object, it was not necessary to load a value from a database for a given id, I load several value => for each id value => for this id and use MultiMap . My MultiMap is a Map, where the keys are id, value is a collection of value that corresponds to id. After the initial data load, I run the generator threads. They work as follows: randomly choose a key from a set of keys, according to this key they receive a collection of values, take 1 value and generate json, which now consists of id and the selected value. Then the selected value is removed from the collection corresponding to our id. If the flow generator detects that the collection for id is empty, then it will submit the task to the pool loader - load me another value for this id
Here, say such a complete picture