如何将带有ReentrantLock的Thread包装到CompletableFuture调用中?

时间:2016-09-29 12:34:44

标签: java java-8 thread-safety

这是我当前的实现,它连续处理不同的文件读取/保存操作:

var myKey = "myObjectKey";
var anArray = ["apple", "balloon", "dog", "cat"];

  store.dispatch({type: 'ADD_ITEM', payload: { [myKey]: anArray} })

我遇到一个问题,即在执行其他操作之前我不会等待线程结果,而且我已经找到了必要的情况。

由于我使用Java 8,我想将它包装在CompletableFuture中。我如何使用当前的实现来实现这一目标?

1 个答案:

答案 0 :(得分:1)

您可以执行以下操作:

  • 您可以使用队列,而不是将下一个作业作为单个引用(this.myThreadImpl)存储,而是在锁定空闲后进行更新。
  • 添加新作业时,会创建一个新的CompletableFuture,并将对它的引用返回给调用者。
  • 一旦工作完成,未来就完成了。

更新您的代码,并假设queueQueue<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。 (例如,它可能是apache commons&#39; ImmutablePair。)

当需要处理内容时,阻止队列通常很有用:https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/BlockingQueue.html

另外,你看过ExecutorService了吗?您可以使用基于单个线程的一个以串行方式执行作业:它的submit(Callable<> task)方法与上面定义的runThread()非常相似,因为它返回Future<Void>这将告诉你什么时候完成任务。