91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

在Java項目中怎么樣實現調度多線程

發布時間:2020-11-20 15:54:56 來源:億速云 閱讀:136 作者:Leah 欄目:編程語言

在Java項目中怎么樣實現調度多線程?針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

        方法一:設置線程優先級。

        java.lang.Thread 提供了 setPriority(int newPriority) 方法來設置線程的優先級,但線程的優先級是無法保障線程的執行次序的,優先級只是提高了優先級高的線程獲取 CPU 資源的概率。也就是說,這個方法不靠譜。

        方法二:使用線程合并。

        使用 java.lang.Thread 的 join() 方法。比如有線程 a,現在當前線程想等待 a 執行完之后再往下執行,那就可以使用 a.join()。一旦線程使用了 a.join(),那么當前線程會一直等待 a 消亡之后才會繼續執行。什么時候 a 消亡?a 的 run() 方法執行結束了 a 就消亡了。

        這個方法可以有效地進行線程調度,但卻只能局限于等待一個線程的執行調度。如果要等待 N 個線程的話,顯然是無能為力了。而且等待線程必須在被等待線程消亡后才得到繼續執行的指令,無法做到兩個線程真正意義上的并發,靈活性較差。

        方法三:使用線程通信。

        java.lang.Object 提供了可以進行線程間通信的 wait 與 notify 、notifyAll 等方法。每個 Java 對象都有一個隱性的線程鎖的概念,通過這個線程鎖的概念我們讓線程間可以進行通信,各線程不再埋頭單干。著名的“生產者-消費者”模型就是基于這個原理實現的。

        這個方法也可以有效地進行線程調度,而且也不僅僅局限于等待一個線程的執行調度,具有很大程度上的靈活性。但操作復雜,不易控制容易造成混亂,程序維護起來也不太方便。

        方法四:使用閉鎖。

        閉鎖就像一扇門,在先決條件未達成之前這扇門是閉著的,線程無法通過,先決條件達成之后,閉鎖打開,線程就可以繼續執行了。java.util.concurrent.CountDownLatch 是一個很實用的閉鎖實現,它提供了 countDown() 和 await() 方法達成線程執行隊列,這個方法最適合 M 個線程等待 N 個線程執行結束再執行的情況。首先初始化一個 CountDownLatch 對象,比如 CountDownLatch doneSignal = new CountDownLatch(N);該對象具有 N 作為計數閥值,每個被等待線程通過對 doneSignal 對象的持有,使用 countDown() 可以將 doneSignal 的計數閥值減一;每個等待線程通過對 doneSignal 對象的持有,使用 await() 阻塞當前線程,直到 doneSignal 計數閥值減為 0,才繼續往下執行。

        這個方法也可以有效地進行線程調度,而且比方法三更易于管理,開發者只需控制好 CountDownLatch 即可。但線程執行次序管理相對單一,它只是指出當前等待線程的數量,而且 CountDownLatch 的初始閥值一旦設置就只能遞減下去,無法重置。如需遞減過程中進行閥值的重置可以參考 java.util.concurrent.CyclicBarrier。

        不管如何,CountDownLatch 對于一定條件下的線程隊列的達成還是很有用的。對于復雜環境下的線程管理還是卓有成效的。所以熟悉和把握對它的使用還是很有必要的。

        以下是一個實際項目中 CountDownLatch 的使用的例子:

 private Map<Long,DecryptSignalAndPath> afterDecryptFilePathMap = new HashMap<Long,DecryptSignalAndPath>();//TODO 注意容器垃圾數據的清理工作 
 class DecryptRunnable implements Runnable { 
   private ServerFileBean serverFile; 
   private Long fid;//指向解密文件 
   private CountDownLatch decryptSignal; 
   protected DecryptRunnable(Long fid, ServerFileBean serverFile, CountDownLatch decryptSignal) { 
     this.fid = fid; 
     this.serverFile = serverFile; 
     this.decryptSignal = decryptSignal; 
   } 
   @Override 
   public void run() { 
     //開始解密 
     String afterDecryptFilePath = null; 
     DecryptSignalAndPath decryptSignalAndPath = new DecryptSignalAndPath(); 
     decryptSignalAndPath.setDecryptSignal(decryptSignal); 
     afterDecryptFilePathMap.put(fid, decryptSignalAndPath); 
     afterDecryptFilePath = decryptFile(serverFile); 
     decryptSignalAndPath.setAfterDecryptFilePath(afterDecryptFilePath); 
     decryptSignal.countDown();//通知所有阻塞的線程 
   } 
    
 } 
 class DecryptSignalAndPath { 
   private String afterDecryptFilePath; 
   private CountDownLatch decryptSignal; 
   public String getAfterDecryptFilePath() { 
     return afterDecryptFilePath; 
   } 
   public void setAfterDecryptFilePath(String afterDecryptFilePath) { 
     this.afterDecryptFilePath = afterDecryptFilePath; 
   } 
   public CountDownLatch getDecryptSignal() { 
     return decryptSignal; 
   } 
   public void setDecryptSignal(CountDownLatch decryptSignal) { 
     this.decryptSignal = decryptSignal; 
   } 
 } 

        需要先執行的,被等待線程在這里加入:

 CountDownLatch decryptSignal = new CountDownLatch(1); 
 new Thread(new DecryptRunnable(fid, serverFile, decryptSignal)).start();//無需拿到新線程句柄,由 CountDownLatch 自行跟蹤 
 try { 
   decryptSignal.await(); 
 } catch (InterruptedException e) { 
   // TODO Auto-generated catch block 
 } 

        需要后執行,等待的線程可以這樣加入:

CountDownLatch decryptSignal = afterDecryptFilePathMap.get(fid).getDecryptSignal();   
 try { 
   decryptSignal.await(); 
 } catch (InterruptedException e) { 
   // TODO Auto-generated catch block 
 } 

        當然,這也僅僅只是一個簡單的 CountDownLatch 的使用展示,對于 CountDownLatch 來說有點大材小用了,因為它可以勝任更復雜的多線程環境。示例中的案例完全可以使用線程通信進行搞定。因為 CountDownLatch 的閥值初始為 1,所以這里甚至完全可以使用方法二所說的線程的合并進行取代。

        如果讀者覺得以上示例不夠清晰,也可以參考 JDK API 提供的 demo,這個清晰明了:

 class Driver2 { // ... 
  void main() throws InterruptedException { 
   CountDownLatch doneSignal = new CountDownLatch(N); 
   Executor e = ... 
  
   for (int i = 0; i < N; ++i) // create and start threads 
    e.execute(new WorkerRunnable(doneSignal, i)); 
  
   doneSignal.await();      // wait for all to finish 
  } 
 } 
  
 class WorkerRunnable implements Runnable { 
  private final CountDownLatch doneSignal; 
  private final int i; 
  WorkerRunnable(CountDownLatch doneSignal, int i) { 
   this.doneSignal = doneSignal; 
   this.i = i; 
  } 
  public void run() { 
   try { 
    doWork(i); 
    doneSignal.countDown(); 
   } catch (InterruptedException ex) {} // return; 
  } 
  
  void doWork() { ... } 
 } 

關于在Java項目中怎么樣實現調度多線程問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

吕梁市| 河池市| 巴彦县| 循化| 九龙县| 临潭县| 灵丘县| 太湖县| 墨竹工卡县| 开鲁县| 柘城县| 天台县| 墨玉县| 易门县| 六盘水市| 盘山县| 成安县| 临汾市| 尉氏县| 丹东市| 格尔木市| 金塔县| 鄱阳县| 大新县| 兰坪| 霸州市| 临朐县| 台东市| 巨鹿县| 桦川县| 望奎县| 建德市| 涪陵区| 民权县| 庐江县| 商河县| 黎城县| 洛川县| 当涂县| 康平县| 册亨县|