CyclicBarrier 一個同步輔助類,它允許一組線程互相等待,直到到達某個公共屏障點 (common barrier point)後,在全部同時執行。
所有的線程調用await()方法之後,到達某個公共屏障點。 然後同時執行 await() 後的操作。
public CyclicBarrier(int parties, Runnable barrierAction) {
}
public CyclicBarrier(int parties) {
}
有兩個構造方法,其中第一個的 barrierAction 參數 是 所有線程調用await()方法之後,到達某個公共屏障點時 會執行的內容。
利用 CyclicBarrier 計算 1+2+3+4+.....+n 的值,代碼如下:
package com.zewe.cyclicBarrier;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 多線程 計算 1+2+3+4+......+n
* @author ZeWe
*
*/
public class CyclicBarrierTest {
private static Integer sum = 0;
private static Integer n = 10005;
private static Integer cyclicSize = 10; //線程數量
private static CyclicBarrier cyclicBarrier;
private static Lock lock;
public static void main(String[] args) {
cyclicBarrier = new CyclicBarrier(cyclicSize,new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"所有子線程相加完畢,準備加和 sum--> sum:"+sum);
}
});
lock = new ReentrantLock();
int avg = n / cyclicSize;
int rem = n % cyclicSize;
int left,right;
for(int i = 1; i<=cyclicSize; i++) {
left = (i-1)*avg+1;
right = i == cyclicSize ? (i*avg+rem) : (i*avg);
new Thread(new Run(left,right)).start();
}
}
static class Run implements Runnable{
private int left;
private int right;
public Run(int left,int right) {
this.left = left;
this.right = right;
}
@Override
public void run() {
int res = 0;
for(int i=left; i<=right; i++) {
res+=i;
}
System.out.println(Thread.currentThread().getName()+" 等待其他線程 --> left:"+left+", right:"+right+", res:"+res);
try {
cyclicBarrier.await(); //等待其他線程執行
} catch (Exception e) {
e.printStackTrace();
}
lock.lock();
try {
sum+=res;
System.out.println(Thread.currentThread().getName()+" 添加至sum --> left:"+left+", right:"+right+", res:"+res+", sum: "+sum);
} finally {
lock.unlock();
}
}
}
}
結果:
Thread-0 等待其他線程 --> left:1, right:1000, res:500500
Thread-4 等待其他線程 --> left:4001, right:5000, res:4500500
Thread-3 等待其他線程 --> left:3001, right:4000, res:3500500
Thread-2 等待其他線程 --> left:2001, right:3000, res:2500500
Thread-1 等待其他線程 --> left:1001, right:2000, res:1500500
Thread-7 等待其他線程 --> left:7001, right:8000, res:7500500
Thread-8 等待其他線程 --> left:8001, right:9000, res:8500500
Thread-6 等待其他線程 --> left:6001, right:7000, res:6500500
Thread-5 等待其他線程 --> left:5001, right:6000, res:5500500
Thread-9 等待其他線程 --> left:9001, right:10005, res:9550515
Thread-9所有子線程相加完畢,準備加和 sum--> sum:0
Thread-9 添加至sum --> left:9001, right:10005, res:9550515, sum: 9550515
Thread-0 添加至sum --> left:1, right:1000, res:500500, sum: 10051015
Thread-7 添加至sum --> left:7001, right:8000, res:7500500, sum: 17551515
Thread-3 添加至sum --> left:3001, right:4000, res:3500500, sum: 21052015
Thread-4 添加至sum --> left:4001, right:5000, res:4500500, sum: 25552515
Thread-2 添加至sum --> left:2001, right:3000, res:2500500, sum: 28053015
Thread-1 添加至sum --> left:1001, right:2000, res:1500500, sum: 29553515
Thread-8 添加至sum --> left:8001, right:9000, res:8500500, sum: 38054015
Thread-6 添加至sum --> left:6001, right:7000, res:6500500, sum: 44554515
Thread-5 添加至sum --> left:5001, right:6000, res:5500500, sum: 50055015