блокировать темы на определенных условиях в Java - PullRequest
1 голос
/ 16 ноября 2011

Может быть, это действительно глупый вопрос, но, пожалуйста, выслушайте меня.У меня есть случай использования, когда я получаю много одновременных запросов на выполнение определенной даты ввода.Если для одной и той же даты ввода получено два одновременных запроса, последующий запрос не должен выполняться до тех пор, пока предыдущий запрос не завершится полностью (по уважительным причинам).Как лучше всего использовать стандартные компоненты java.util.concurrent для достижения этой цели?Мои первые мысли были о том, чтобы иметь LockFactory, которая будет продавать блокировки и сохранять копию, чтобы указать, что она используется и о которой последующий запрос будет ожидать ().Тем не менее, кажется, что в этом есть много кода для котла - какой-нибудь более простой трюк, который ускользает от меня?

Заранее спасибо!

Ответы [ 5 ]

1 голос
/ 16 ноября 2011

Вы можете хешировать отдельные блокировки по времени даты.

private static final ConcurrentMap<Long,Lock> dateLock = new ConcurrentHashMap<Long,Lock>();

public static Lock getLock(Date date){
  Lock lock = dateLock.get(date.getTime());  
  if(lock == null){
    Lock lock = new ReentrantLock();  
    Lock temp =dateLock.putIfAbsent(lock); 
    lock = temp == null ? lock : temp;
  }
 return lock;
}

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

private static final ConcurrentMap<String,Lock> dateLock = new ConcurrentHashMap<String,Lock>();

public static Lock getLock(Date date){ 
  String formattedDate = new SimpleDateFormat("MM\dd\yyyy").parse(date);
  Lock lock = dateLock.get(formattedDate);  
  if(lock == null){
    Lock lock = new ReentrantLock();  
    Lock temp =dateLock.putIfAbsent(lock); 
    lock = temp == null ? lock : temp;
  }
 return lock;
}

Затем любой запрос, который требует взаимного исключения в дату

Date date = ...;

Lock lock = getLock(date);
lock.lock(); 

и пр.

1 голос
/ 16 ноября 2011

Вам необходимо создать ThreadPoolExecutor для выполнения запросов в нескольких потоках.Также вам необходимо иметь список вводимых дат, которые обрабатываются сейчас.Этот список должен иметь синхронные методы доступа и метод putIfAbsent.Перед отправкой задачи в очередь убедитесь, что ее дата ввода не обрабатывается.Если он обрабатывается сейчас, переместите эту задачу в конец очереди и попробуйте выполнить следующую задачу.После завершения задачи удалите введенную дату из списка.

1 голос
/ 16 ноября 2011

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

Вам потребуется определенное количество блокировок, чтобы гарантировать, что «текущая работа над записью» не обновляется при тестировании.

1 голос
/ 16 ноября 2011

Звучит так, будто вы должны ставить в очередь свои запросы и обрабатывать их по одному.Так что, возможно, BlockingQueue из java.util.concurrent?

0 голосов
/ 17 ноября 2011

Простой трюк, который вам нужен, - это пул потоков с шаблоном обработки заказов. Вот поток, который объясняет шаблон и различные решения для его реализации

...