利用線程池,同步線程實現並發


一、CountDownLatch

同步工具類,允許一個或多個線程等待,直到其他的線程操作完成后在執行。

如何工作:

CountDownLatch是通過一個計數器來實現的,計數器的初始值為線程的數量。每當一個線程完成了自己的任務后,計數器的值就會減1。當計數器值到達0時,它表示所有的線程已經完成了任務,然后在閉鎖上等待的線程就可以恢復執行任務。

使用場景:

1.實現最大的並行性:有時我們想同時啟動多個線程,實現最大程度的並行性。例如,我們想測試一個單例類。如果我們創建一個初始計數為1的CountDownLatch,並讓所有線程都在這個鎖上等待,那么我們可以很輕松地完成測試。我們只需調用 一次countDown()方法就可以讓所有的等待線程同時恢復執行。

2.開始執行前等待n個線程完成各自任務:例如應用程序啟動類要確保在處理用戶請求前,所有N個外部系統已經啟動和運行了。

3。死鎖檢測:一個非常方便的使用場景是,你可以使用n個線程訪問共享資源,在每次測試階段的線程數目是不同的,並嘗試產生死鎖。

 

二、使用countdownlach 和ExecutorService 線程池 編寫並發

 countdownlach 同步計數設置為1,countDown 則線程並發

package com.cyd.util.netty;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * countdownlach 和線程池完成並發 應用場景:1、最大並發。2、執行前等待N線程執行完成。 3、模擬鎖死。
 * 
 * @author chenyd 2017年11月29日
 */
public class Concurrent {

    public static void main(String[] args) {
        int threadNum = 5;
        CountDownLatch countd = new CountDownLatch(1);// 同步線程數
        ExecutorService threadPool = Executors.newFixedThreadPool(threadNum);// 線程池
        for (int i = 0; i < threadNum; i++) {
            threadPool.execute(new ChildThread(i,countd));
        }
        try {
            System.out.println("等待添加....");
            Thread.sleep(1000);
            System.out.println("並發....");
            countd.countDown();
        
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            threadPool.shutdown();
            // 關閉線程池,停止所有正在執行的活動任務,暫停處理正在等待的任務,並返回等待執行的任務列表。
            // threadPool.shutdownNow();
        }
    }

}

class ChildThread implements Runnable {
    private int num;
    private CountDownLatch countd;
    public ChildThread(){};
    public ChildThread(int num,CountDownLatch countd) {
        this.num = num;
        this.countd=countd;
    };

    public void run() {
        try {
            countd.await();
            // 使當前線程在鎖存器倒計數至零之前一直等待,除非線程被中斷或超出了指定的等待時間。
            // latch.await(long timeout, TimeUnit unit);
            System.out.println("子線程:" + num);
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //當前計算工作結束,計數器減一
            
            try {
                //Thread.sleep(10);
            } catch (Exception e) {
                e.printStackTrace();
            }
             //執行coutDown()之后,繼續執行自己的工作,不受主線程的影響
            System.out.println("子線程"+num+"繼續執行,不受影響");
        }
    }

}

 

參考鏈接:

什么時候使用CountDownLatchhttp://www.importnew.com/15731.html

java多線程CountDownLatch及線程池ThreadPoolExecutor/ExecutorService使用示例http://blog.csdn.net/javaloveiphone/article/details/54729821

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM