java: Executors + tasks + locks

Предположим, у меня есть ExecutorService (который может быть пулом потоков, поэтому здесь задействован параллелизм), который выполняет задачу в разное время, либо периодически, либо в ответ на какое-либо другое условие. Задача, которая должна быть выполнена, следующая:

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

Я пытаюсь придумать способ реализовать это. Это должно быть примерно так:

Runnable task = new Runnable() {
   final SomeObj inProgress = new SomeObj();
   @Override public void run() {
       if (inProgress.acquire())
       {
          try
          {
             algorithmX();
          }
          finally
          {
             inProgress.release();
          }
       }
   }
}

// re-use this task object whenever scheduling the task with the executor

где SomeObj либо ReentrantLock (Acquire = tryLock () и release = unlock () ]) или AtomicBoolean или что-то в этом роде, но я не уверен, какой именно. Нужен ли мне здесь ReentrantLock? (Может быть, мне нужна блокировка без повторного входа в случае, если algorithmX () заставляет эту задачу запускаться рекурсивно!) Или будет достаточно AtomicBoolean?


edit: для блокировки без повторного входа, это уместно?

Runnable task = new Runnable() {
   boolean inProgress = false;
   final private Object lock = new Object();
   /** try to acquire lock: set inProgress to true, 
    *  return whether it was previously false
    */ 
   private boolean acquire() {
      synchronized(this.lock)
      {
         boolean result = !this.inProgress;
         this.inProgress = true;
         return result;
      }
   }
   /** release lock */
   private void release() {
      synchronized(this.lock)
      {
         this.inProgress = false;
      }
   }
   @Override public void run() {
       if (acquire())
       {
          // nobody else is running! let's do algorithmX()
          try
          {
             algorithmX();
          }
          finally
          {
             release();
          }
       }
       /* otherwise, we are already in the process of 
        * running algorithmX(), in this thread or in another,
        * so don't do anything, just return control to the caller.
        */
   }
}

5
задан Jason S 2 February 2011 в 17:09
поделиться