2016-12-13 1 views
0

Я вычисляю задержки в моем приложении (в миллисекундах), и я хочу вставить эти метрики в структуру списка безопасных потоков. И затем я буду использовать этот список для вычисления среднего, среднего, 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); 
    } 
+0

вы предлагаете то же самое идентификатор процесса может быть назначен несколько раз. Это правда, но любая достойная ОС будет перерабатывать ID с очень большим периодом. Я предполагаю, что вы очистите статистику при печати, так что, скорее всего, у вас закончится память, потому что вы сохраняете статистику намного раньше, чем идентификатор процесса перерабатывается. В противном случае, как вы планируете выяснить, существует ли существующая запись для PID для этого процесса или была создана для предыдущего экземпляра с тем же PID? –

+0

Не связаны processId с unix PID. Это просто наш собственный идентификатор процесса для другого термина. – john

+0

и как вы отличаете случай одного и того же экземпляра от двух экземпляров с одинаковым идентификатором? –

ответ

0

нормально, я не уверен, что я получаю все данные правильно, но это один из способов сделать это:

public class LatencyMetricHolder { 

HashMap<Integer, ConcurrentLinkedQueue<Long>> map = new HashMap<>(); 

public void addLatency(int processID, long latency) { 
    synchronized(map) { 
     ConcurrentLinkedQueue<Long> q = map.get(processID); 
     if (q == null) { 
     q = new ConcurrentLinkedQueue<Long>() 
     map.put(processID, q); 
     } 
    } 
    q.add(latency) 
    } 

    public ConcurrentLinkedQueue<Long> getLatenciesHolder(int processID) { 
    synchronized(map) { 
     return map.get(processId); 
    } 
    } 
} 
Смежные вопросы