2013-11-01 2 views
0

Я столкнулся со следующей проблемой: Я реализовал искатель, и я хотел бы знать, сколько запросов было выполнено в течение последней секунды, и какой объем данных был загружается в течение последней секунды.Как реализовать счетчик атомарного запроса

В настоящее время я реализовал его с помощью замков. Моя версия использует очередь и два счетчика (счет и сумма). Когда задача выполнена, я просто увеличиваю счетчики, и добавляю событие (с текущей датой) в очередь Когда вы хотите получить значение моих счетчиков, я проверяю, есть ли какие-то вещи в очереди более 1секунды старый. Если это так, я удаляю его и правильно уменьшаю счетчики. Затем я возвращаю желаемый результат.

Эта версия работает хорошо, но я хотел бы, для целей обучения, переопределить ее с помощью атомных операций вместо блокировок. Тем не менее, я должен признать, что я застрял на «операции очистки». (дезертировка старых значений)

Итак, это хороший подход, чтобы реализовать это?

Какой другой подход я мог использовать?

Спасибо!

ответ

1

Эта версия работает хорошо, но я хотел бы, для целей обучения, переопределить ее с помощью атомных операций вместо блокировок.

Если вам нужно внести несколько изменений в данные, когда произойдет период рулона, вам нужно будет заблокировать, иначе у вас будут проблемы. Каждый раз, когда у вас есть несколько «атомных операций», вам необходимо иметь блокировку для защиты от условий гонки. Например, в вашем случае, что, если что-то еще было добавлено в очередь, пока вы делали свой бросок?

Какой другой подход я мог использовать?

Я не уверен на 100%, почему вам нужно поставить в очередь информацию. Если вы только подсчитываете количество запросов и общее количество загружаемых данных, вы должны иметь возможность использовать один AtomicReference<CountSum>. Класс CountSum сохранит ваши два значения. Затем, когда кому-то нужно увеличить его они будут делать что-то вроде:

CountSum newVal = new CountSum(); 
do { 
    CountSum old = countSumRef.get(); 
    newVal.setCount(old.getCount() + 1); 
    newVal.setSum(old.getSum() + requestDataSize); 
    // we need to loop here if someone changed the value behind our back 
} while (!countSumRef.compareAndSet(old, newVal)); 

Это гарантирует, что ваш счетчик и ваша сумма всегда синхронизированы. Если вы использовали две переменные AtomicLong, вам нужно будет сделать два атомных запроса и понадобится блокировка снова.

Если вы хотите сбросить значения, вы сделали бы то же самое.

CountSum newVal = new CountSum(0, 0); 
CountSum old; 
do { 
    old = countSumRef.get(); 
    // we need to loop here if someone changed the value behind our back 
} while (!countSumRef.compareAndSet(old, newVal)); 
// now you can display the old value and be sure you got everything 
+0

Мне нужна эта система очередей, потому что я не хочу глобального запроса, а номер запроса, сделанного в течение последней секунды. В моем случае абсолютный подсчет невозможен. – Nisalon

+0

Понял. Поэтому каждую секунду поток будет выполнять второй блок кода, который сбрасывает значения @Nisalon. Правильно? – Gray

+0

Не совсем. Потому что я не хочу читать каждую секунду, я хочу прочитать, что произошло за последние 1000 мс. Если я использую ваш метод, то при t = 1500 мс я ожидаю, что данные о задачах будут завершены во время t = 500ms && t = 1500ms Используя ваш метод, у меня будут данные о задачах, завершенных во время t = 1000 мс && t = 1500ms – Nisalon

Смежные вопросы