多執行緒學習筆記之十四——CountDownLatch、 CyclicBarrie、Semaphore的使用
阿新 • • 發佈:2018-12-09
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();
}
}
執行結果是每十個執行緒併發執行。