2016-09-29 2 views
0

Это моя текущая реализация, которая обрабатывает другой файл для чтения/сохранения операции последовательно:Как обернуть Thread с ReentrantLock в CompletableFuture?

public void runThread(MyThreadImpl myThreadImpl) { 
    synchronized (this) { 
     this.myThreadImpl = myThreadImpl; 
     notify(); 
    } 
} 

synchronized public void run() { 
    while (true) 
     try { 
      wait(); 
      Global.myReentrantLock.lock(); 
      try { 
       try { 
        myThreadImpl.call(); 
       } catch (FileException e) { 
        // trace e 
       } catch (RuntimeException e) { 
        // trace e 
       } catch (Exception e) { 
        // trace e 
       } 
      } finally { 
       Global.myReentrantLock.unlock(); 
      } 
     } catch (InterruptedException e) { 
      // trace e 
     } catch (Exception e) { 
      // trace e 
     } 
} 

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

Поскольку я использую Java 8, я хотел бы обернуть это в CompletableFuture. Как я могу сделать это с моей текущей реализацией?

ответ

1

Вы можете сделать следующее:

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

Обновление кода, и предполагая queue выстраивается очередь блокирование типа Queue<Pair<CompletableFuture<Void>, MyThreadImpl>>, вы бы:

/** 
* @return a Future that will complete once the passed MyThreadImpl has been run. 
*/ 
public CompletableFuture<Void> runThread(MyThreadImpl myThreadImpl) { 
    Pair<CompletableFuture<Void>, MyThreadImpl> p = 
       new Pair<>(new CompletableFuture<>(),myThreadImpl); 
    queue.add(p); 
    return p.left; 
} 

public void run() { 
    while (true) { 
     try { 

      Pair<CompletableFuture<MyThreadImpl>, MyThreadImpl> p = 
        queue.take(); // will block until a job is added 

      try { 
       p.right.call(); 
       p.left.complete(null); // Future<Void> can only be completed with null. Alternatively, it could be completed with a relevant result. 
      } catch (Exception e) { 
       p.left.completeExceptionally(e); 
      } 

     } catch (InterruptedException e) { 
      // trace e 
     } 
    } 
} 

Здесь Pair просто должна быть пара, как POJO. (Это может быть апач Обще-х ImmutablePair, например.)

Блокирующие очереди, как правило, полезны, когда материал должен быть обработан: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/BlockingQueue.html

Кроме того, вы смотрели на ExecutorService? Вы можете использовать один, основанный на одном потоке, для выполнения заданий в последовательном порядке: это метод submit(Callable<> task), как это определено выше, как runThread(), так как он возвращает Future<Void>, который расскажет вам, когда задача будет выполнена.

Смежные вопросы