2015-06-13 5 views
0

У меня есть ExecutorService как этотExecutorService справедливость

ExecutorService executor = new ThreadPoolExecutor(threads, threads, 
      0L, TimeUnit.MILLISECONDS, 
      new ArrayBlockingQueue<>(1000, true)); 

и я шлю работу к нему с .Execute (Runnable)

Моих работоспособными имеет

 @Override 
     public void run() { 
      this.processor.performAction(this); 
     } 

где процессор имеет

public void performAction(RunnableAction action) { 
     Lock lock = lockManager.getLock(action.getId()); 
     lock.lock(); 
     try { 
      action.execute(); 
     } finally { 
      lock.unlock(); 
     } 
    } 

, где lockManager является

public class LockManager { 

    Map<String, Lock> lockById = new HashMap<>(1000); 

    public synchronized Lock getLock(String id) { 
     Lock lock = lockById.get(id); 
     if (lock == null) { 
      lock = new ReentrantLock(true); 
     } 
     return lock; 
    } 

и мои действия/Runnable есть поле execQty, который запускает обновление на несколько порядков, призывающих их order.execute (execQty)

public void execute(int execQty) { 
     if (execQty < this.lastExecQty) { 
      System.err.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); 
      System.err.println("id: " + this.id + " wrong order" + this.lastExecQty + " > " + execQty); 
     } 
     this.execQty += execQty; 
     this.lastExecQty = execQty; 
    } 
} 

Я заказал мои runnables отправить в планировщик всегда имея QTY поле каждый больше, чем предыдущий, поэтому при печати каждой работоспособной перед его отправкой в ​​ExecutorService я всегда получаю то, что мне нужно, заказал номера:

execute: id: 49 qty: 819 
execute: id: 49 qty: 820 
execute: id: 49 qty: 821 
execute: id: 49 qty: 822 
execute: id: 49 qty: 823 

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

execute: id: 88 qty: 6 
execute: id: 88 qty: 7 
execute: id: 88 qty: 8 
execute: id: 88 qty: 9 
execute: id: 88 qty: 10 
execute: id: 88 qty: 11 
execute: id: 88 qty: 12 
execute: id: 88 qty: 13 
execute: id: 88 qty: 14 
execute: id: 88 qty: 15 
execute: id: 88 qty: 16 
execute: id: 88 qty: 17 
execute: id: 88 qty: 18 
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
id: 88 wrong order 17 (previous) > 7 (current) 
execute: id: 88 qty: 19 
execute: id: 88 qty: 20 

Он отлично работает при запуске ExecutorService с только одна нить

ответ

1

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

Предложенное изменение:

public synchronized Lock getLock(String id) { 
    Lock lock = lockById.get(id); 
    if (lock == null) { 
     lock = new ReentrantLock(true); 
     // put lock into the map so that next one will reuse it 
     lockById.put(id, lock); 
    } 
    return lock; 
}