2010-04-01 5 views
1

У меня следующий сценарий многопоточной среды - запросы идут к методу, и я хочу избежать дублирования обработки одновременных запросов. Поскольку несколько похожих запросов могут ждать обработки в заблокированном состоянии. Я использовал хеш-таблицу для отслеживания обработанного запроса, но это создаст утечки памяти, поэтому как следует отслеживать обработанный запрос и избегать обработки тех же запросов, которые могут быть заблокированы.Java Multi threading - Избегайте дублирования обработки запроса

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

+0

Я не понимаю, что вы имеете в виду. Вы имеете в виду равные запросы, поступающие в несколько раз, но вы хотите только обрабатывать такой запрос один раз? –

+0

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

ответ

1

Если проблема с утечкой памяти является проблемой, обратите внимание на WeakHashMap, чтобы сохранить ваш запрос во время обработки.

Другим решением было бы использовать память, связанную кэш ...

+0

Я думал об этом, но есть ли способ сделать это без использования какой-либо структуры данных. путем структурирования проверок блокировки и проверки условий каким-либо образом – seawaves

+0

Также мы никогда не знаем, когда будет удалена запись weakhashmap, если она будет удалена до обработки всех заблокированных запросов, тогда произойдет повторная обработка запроса. – seawaves

1

Хорошо, я думаю, что я вроде понимаю, что вы хотите.

Вы можете использовать ConcurrentSkipListSet в качестве очереди. Реализовать свои очереди элементов, как это:

class Element implements Comparable<Element> { 
     //To FIFOnize 
     private static final AtomicLong SEQ = new AtomicLong(); 
     private final long id = SEQ.incrementAndGet(); 

     //Can only be executed once. 
     private final Semaphore execPermission = new Semaphore(1); 


     public int compareTo(Element e){ 
      // If element e1 exists on the queue such that 
      // e.compareTo(e1) == 0, that element will not 
      // be placed on the queue. 
      if(this.equals(e)){ 
       return 0; 
      }else{ 
       //This will enforce FIFO. 
       this.id > e.id ? 1 : (this.id < e.id ? -1 : 0); 
      } 
     } 
     //implement both equals and hashCode 

     public boolean tryAcquire(){ 
      return execPermission.tryAcquire(); 
     } 
} 

Теперь ваши темы должны

while(!Thread.currentThread().isInterrupted()){ 
    //Iterates from head, therefore simulates FIFO 
    for(Element e : queue){ 
      if(e.tryAcquire()){ 
       execute(e); //synchronous 
       queue.remove(e); 
      } 
    } 
} 

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

1

Не существует неотъемлемой причины, по которой отслеживание запросов в HashMap (или любой другой способ, который вы можете выбрать) приведет к утечке памяти. Все, что необходимо - это способ удаления записей после их обработки.

Это может означать, ваши потоки обработки запроса:

  • непосредственно удалить запись;
  • обращается к диспетчеру; или
  • отметьте запрос обработанным, поэтому , чтобы диспетчер мог удалить записи.
+0

При каких условиях я должен очистить hashmap, как я узнаю, что нет ожидающего потока, который имеет тот же запрос, что и обработанные. – seawaves

+0

@seawaves: Когда нет очереди с тем же запросом. Когда диспетчер получает запрос, для которого уже существует поток, вы собираетесь создать поток, который будет обрабатывать его, не так ли? Поэтому у вашего диспетчера уже есть набор запросов, набор запущенных потоков и набор ожидающих потоков. * (строчный «набор» - общий математический термин, а не какая-либо конкретная структура данных) *. Итак, ваш диспетчер, обнаружив, что выполняемый поток для запроса X завершен, проверяет, ждут ли какие-либо другие потоки для работы на X, и либо удаляет его, либо запускает одного из официантов. – CPerkins