2016-09-29 58 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>,它會告訴您任務何時完成。

相關問題