EventCounter - счетчик событий, поддерживающий операции:
- регистрация события
- получение количества событий за последний промежуток времени (минута, час, день)
ConcurrentEventCounter это thread-safe реализация EventCounter. При регистрации нового события, время события записывается в буфер. Одновременно с этим инкрементируются счетчики количества событий за последнюю минуту, час и день. Инкрементируются сразу все, несмотря на то, что событие пока добавлено только в буфер.
Заполнение очередей: При вызове конструктора инициализируются четыре ScheduledExecutorService.
Поток создаваемый bufferCleaner достает события из буфера, объединяет события произошедшие в течение одной секунды в объект класса EventsBucket. Где time - время к которому можно отнести набор событий, countOfEvents - количество объединенных событий. Далее объект EventsBucket с объединенными событиями помещается в очередь событий последней минуты. При этом счетчики событий не изменяются.
Поток создаваемый minuteCleaner проверяет очередь событий последней минуты на появление устаревших событий. Все устаревшие события перемещаются в очередь событий последнего часа. При этом счетчик событий последнего часа не изменяется, а счетчик событий последней минуты уменьшается на количество устаревших событий.
Поток создаваемый hourCleaner проверяет очередь событий последнего часа на появление устаревших событий. Все устаревшие события перемещаются в очередь событий последнего дня. При этом счетчик событий последнего дня не изменяется, а счетчик событий последнего часа уменьшается на количество устаревших событий.
Поток создаваемый dayCleaner проверяет очередь событий последнего дня на появление устаревших событий. Все устаревшие события удаляются из очереди. Счетчик событий последнего дня уменьшается на количество устаревших событий.
Сейчас разбор буфера работает в один поток, поэтому события сжимаются (объединяются) максимально. Можно запустить разбор буфера в несколько потоков, тогда скорость разбора будет выше, но количество объектов EventsBucket в памяти будет больше. Разбор буфера поддерживает работу в несколько потоков. В отличии от разбора буфера - разбор очереди минуты/часа/дня должен происходить строго в одном потоке в один момент времени. Однопоточный разбор этих очередей допускается, так как объектов в них на много меньше, чем в очереди буфера.
Также, возможно, есть смысл держать в памяти данные только за последний час. А остальные данные хранить на диске.