1. 程式人生 > >多執行緒學習筆記之十四——CountDownLatch、 CyclicBarrie、Semaphore的使用

多執行緒學習筆記之十四——CountDownLatch、 CyclicBarrie、Semaphore的使用

CountDownLatch

CountDownLatch的構造器:

public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

count引數可以通俗的理解為countDown()方法呼叫的次數,當count和呼叫次數相同時,await()方法的執行緒才能繼續執行。 注意:countDown()不一定是另一個執行緒呼叫。 CountDownLatch的示例:

package day3;

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

public class CountDownLatchTest {
    private CountDownLatch c = new CountDownLatch(2);

    public static void main
(String[] args) throws InterruptedException { CountDownLatchTest test = new CountDownLatchTest(); ExecutorService executor = Executors.newFixedThreadPool(2); sumEven sumEven = test.new sumEven(1,100); sumOdd sumOdd = test.new sumOdd(1,100); executor.submit(sumEven); executor.submit(sumOdd); long
start = System.currentTimeMillis(); System.out.println("等待結果"); test.c.await(); System.out.println("等待時間:"+(System.currentTimeMillis() - start)); System.out.println("偶數和:"+sumEven.getSumEven()); System.out.println("奇數和:"+sumOdd.getSumOdd()); executor.shutdown(); } class sumEven implements Runnable{ private int start; private int end; private int sumEven; public int getSumEven() { return sumEven; } public void setSumEven(int sumEven) { this.sumEven = sumEven; } public sumEven(int start,int end) { this.start = start; this.end = end; } @Override public void run() { try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } sumEven = sumEvenM(start,end); c.countDown(); } public int sumEvenM(int start,int end) { int sum = 0; for(int i = start;i<=end;i++) { if(i%2==0) { sum = sum +i; } } return sum; } } class sumOdd implements Runnable{ private int start; private int end; private int sumOdd; public int getSumOdd() { return sumOdd; } public void setSumOdd(int sumOdd) { this.sumOdd = sumOdd; } public sumOdd(int start,int end) { this.start = start; this.end = end; } @Override public void run() { try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } sumOdd = sumOddM(start,end); c.countDown(); } public int sumOddM(int start,int end) { int sum = 0; for(int i = start;i<=end;i++) { if(i%2==1) { sum = sum +i; } } return sum; } } }

解釋:此示例開啟了倆個執行緒,分別用來算奇數和與偶數和,等待算完後打印出來。 console輸出:

等待結果
等待時間:2001
偶數和:2550
奇數和:2500

應用場景:適用於最後需要統計結果的程式,但本人感覺這種功能可以直接用fork/join框架來處理

CyclicBarrier

感覺跟CountDownLatch差不錯

Semaphore

控制執行緒的併發數,示例如下:

package day3;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class SemaphoreTest {
    private static final int THREAD_COUNT = 30;
    private static ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_COUNT);
    private static Semaphore s = new Semaphore(10);
    private static AtomicInteger j = new AtomicInteger(0);

    public static void main(String[] args) {
        for (int i = 0; i < THREAD_COUNT; i++) {
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        s.acquire();
                        System.out.println("save data"+(j.incrementAndGet()));
                        TimeUnit.SECONDS.sleep(10);
                        s.release();
                    } catch (InterruptedException e) {
                    }
                }
            });
        }
        threadPool.shutdown();
    }
}

執行結果是每十個執行緒併發執行。