2016-09-29 51 views
0

这是我目前的执行负责处理不同文件的读/连续保存操作:如何将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,并将其引用返回给调用者。
  • 工作完成后,未来就完成了。

更新你的代码,并假设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。 (这可能是阿帕奇公地的ImmutablePair,例如。)

阻塞队列的东西需要处理时,通常是有用的:https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/BlockingQueue.html

而且,你看ExecutorService?您可以使用基于单个线程的方式以串行方式执行作业:它的方法非常类似于上面定义的runThread(),因为它返回一个Future<Void>,它会告诉您任务何时完成。

相关问题