Я вычисляю задержки в моем приложении (в миллисекундах), и я хочу вставить эти метрики в структуру списка безопасных потоков. И затем я буду использовать этот список для вычисления среднего, среднего, 95-го процентиля позже. Так что я looked его и я не видел много вариантов со списком, поэтому я решил использовать ConcurrentLinkedQueue
для хранения задержек, которые являются потокобезопасными. Если есть какая-либо другая более надежная структура данных, защищенная потоками, которую я должен использовать для этого, дайте мне знать.Как добавить задержки в ConcurrentLinkedQueue, который является частью карты ConcurrentMap в атомном режиме?
public class LatencyMetricHolder {
private final ConcurrentLinkedQueue<Long> latenciesHolder = new ConcurrentLinkedQueue<>();
private static class Holder {
private static final LatencyMetricHolder INSTANCE = new LatencyMetricHolder();
}
public static LatencyMetricHolder getInstance() {
return Holder.INSTANCE;
}
private LatencyMetricHolder() {}
public void addLatencies(long latency) {
latenciesHolder.add(latency);
}
public ConcurrentLinkedQueue<Long> getLatenciesHolder() {
return latenciesHolder;
}
}
Я зову addLatencies
метод для заполнения латентности из многопоточного кода.
Теперь я хочу иметь latenciesHolder
для каждого processId
, который является строкой. Это означает, что мы также можем получить одинаковые processId
несколько раз, и иногда это будет новый processId
, поэтому почему-то мне нужно извлечь очередь latenciesHolder
для этого processId
и добавить латентность в этой конкретной очереди потоковым безопасным способом и атомным способом.
Поэтому я решил использовать параллельную карту для этого, как показано ниже, где ключ будет processId
:
private final Map<String, ConcurrentLinkedQueue<Long>> latenciesHolderByProcessId = Maps.newConcurrentMap();
Поскольку я использую карту, то мне нужно синхронизировать по созданию новых ConcurrentLinkedQueue
экземпляров, который вроде сложно в Java 7 Я предполагаю, что я нахожусь на Java 7.
Каков правильный способ заполнить эту карту атомарным способом из нескольких потоков без особых противоречий, и я хочу использовать параллельные коллекции вместо обычной блокировки, если есть какой-то способ?
Update:
public void add(String type, long latencyInMs) {
ConcurrentLinkedQueue<Long> latencyHolder = latenciesHolderByProcessId.get(type);
if (latencyHolder == null) {
latencyHolder = Queues.newConcurrentLinkedQueue();
ConcurrentLinkedQueue<Long> currentLatencyHolder =
latenciesHolderByProcessId.putIfAbsent(type, latencyHolder);
if (currentLatencyHolder != null) {
latencyHolder = currentLatencyHolder;
}
}
latencyHolder.add(latencyInMs);
}
вы предлагаете то же самое идентификатор процесса может быть назначен несколько раз. Это правда, но любая достойная ОС будет перерабатывать ID с очень большим периодом. Я предполагаю, что вы очистите статистику при печати, так что, скорее всего, у вас закончится память, потому что вы сохраняете статистику намного раньше, чем идентификатор процесса перерабатывается. В противном случае, как вы планируете выяснить, существует ли существующая запись для PID для этого процесса или была создана для предыдущего экземпляра с тем же PID? –
Не связаны processId с unix PID. Это просто наш собственный идентификатор процесса для другого термина. – john
и как вы отличаете случай одного и того же экземпляра от двух экземпляров с одинаковым идентификатором? –