从这章开始介绍 java.concurrent.*中的常用并发工具类,并附带有趣的示例
概要
比如5个任务同时运行,Task F 要求在 Task A 、Task B 、Task C、Task D、Task E 都完成后执行.那么使用CountDownLatch对象,并设置一个初始值,如 CountDownLatch countDownLatch = new CountDownLatch(5).
在Task F中调用countDownLatch.await()阻塞该任务,直到count值为0时,自动运行。
Task A....Task E ,这5个任务中,调用countDownLatch.countDown(),表示每完成一个任务就将count值减一.
Task A...E运行完之后,Task F将不再阻塞,立刻运行
以上描述对应代码实现:
class PortionTask implements Runnable {
private static int counter = 0;
private int id = counter++;
private CountDownLatch countDownLatch;
public PortionTask(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
System.out.println("portion task complete " + this + " Thread[" + Thread.currentThread().getName() + "]");
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
countDownLatch.countDown();
}
@Override
public String toString() {
return "PortionTask [id=" + id + "]";
}
}
class TaskWaiting implements Runnable {
private CountDownLatch countDownLatch;
public TaskWaiting(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
try {
countDownLatch.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("it's my turn " + this);
}
}
public class CountDownLatchDemoMine {
public static void main(String[] args) {
int SIZE = 5;
CountDownLatch c = new CountDownLatch(SIZE);
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new PortionTask(c));// A Task
exec.execute(new PortionTask(c));// B Task
exec.execute(new PortionTask(c));// C Task
exec.execute(new PortionTask(c));// D Task
exec.execute(new PortionTask(c));// E Task
exec.execute(new TaskWaiting(c));// Final Task F
exec.shutdown();
}
}
直接上代码,一个很多有趣的短跑比赛模拟程序,详见注释,看完你就理解了CyclicBarrier:
class Player implements Runnable {
private static int counter = 0;
private int id = counter++;
private int moveDistance;
private static CyclicBarrier barrier;
private static Random random = new Random(47);
public Player(CyclicBarrier b) {
barrier = b;
}
public int getMoveDistance() {
return moveDistance;
}
@Override
public void run() {
while (!Thread.interrupted()) {
moveDistance += random.nextInt(3);
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
@Override
public String toString() {
return "" + id;
}
}
public class Race {
private int playerNum = 5;
private int finalLine = 20;
private CyclicBarrier barrier;// 唯一的CyclicBarrier对象
private List<Player> players = new ArrayList<Player>();
private ExecutorService es = Executors.newCachedThreadPool();
public Race() {
// 1 构建CyclicBarrier(int parties, Runnable barrierAction)
// 当n个player都在这个barrier上调用了barrier.await(),这个barrier
// 对象将重置,并使用最后一个调用await的线程去运行barrierAction,
// 唤醒所有wait的线程,
// 然后再一次等待nHourse全部执行await....周而复始;直到shutdownNow
// 查看CyclicBarrier构造器的JDoc,有详细描述
barrier = new CyclicBarrier(playerNum, new Runnable() {
@Override
public void run() {
// 1.打印赛道
StringBuffer raceLine = new StringBuffer();
raceLine.append(" ");
for (int i = 0; i < finalLine; i++) {
raceLine.append("=");
}
System.out.println(" 100米男子赛道");
System.out.println(raceLine);
// 2.打印当前参赛者行进位置
for (Player player : players) {
StringBuffer playerLocation = new StringBuffer();
playerLocation.append(player);
for (int i = 0; i < player.getMoveDistance(); i++) {
playerLocation.append("*");
}
System.out.println(playerLocation);
}
// 3.检查是否有参赛者完成比赛,如果是,结束比赛;
// (会存在多个player同时越过终点)
for (Player player : players) {
if (player.getMoveDistance() >= finalLine) {
System.out.println("bravo: player" + player + " won!!! ");
es.shutdownNow();// 该方法并不保证池中所有线程退出
return;
}
}
try {
TimeUnit.MILLISECONDS.sleep(80);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// 2.任务执行:所有player开始跑
for (int i = 0; i < playerNum; i++) {
// 每个Player中传入同一个CyclicBarrier对象
Player p = new Player(barrier);
players.add(p);
es.execute(p);
}
}
public static void main(String[] args) {
new Race();
}
}
output:
100米男子赛道
==========
0**
1**
2*
3**
4*
..............................
100米男子赛道
==========
0*******
1*********
2*****
3******
4******
100米男子赛道
==========
0********
1**********
2*****
3*******
4******
bravo: player1 won!!!
示例描述:
一个生产者线程生产消息 msgX,然后调用exchanger.exchang(msgX),此时该线程Blocked,等待另一个线程(消费者)去消费:消费者调用 exchanger.exchange(“此参数会传递给生产者线程,并不需要”),获得生成者刚才生成的消息,并唤醒阻塞的生产者.
public class ExchangerTest {
private static final Exchanger<List<String>> exgr = new Exchanger<List<String>>();
private static ExecutorService threadPool = Executors.newFixedThreadPool(10);
private static Random rand = new Random(47);
private static Runnable producerProductMsg() {
return new Runnable() {
@Override
public void run() {
List<String> producerMsgX = new ArrayList<String>();
for (int i = 0; i < 10; i++) {
producerMsgX.add(i + rand.nextInt(100) + "");
}
try {
// 生产,阻塞
// Waits for another thread to arrive at this exchange
// point
exgr.exchange(producerMsgX);
System.out.println(" ThreadName:" + Thread.currentThread().getName() + " producerProductMsg:"
+ producerMsgX);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
}
private static Runnable consumerConsumeMsg() {
return new Runnable() {
@Override
public void run() {
try {
List<String> getMsgFromProducer = exgr.exchange(new ArrayList<String>());
System.out.println(" ThreadName:" + Thread.currentThread().getName() + " consumerConsumeMsg:"
+ getMsgFromProducer);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
}
public static void main(String[] args) {
// 消息生成者
threadPool.execute(producerProductMsg());
// 消费者 消费
threadPool.execute(consumerConsumeMsg());
threadPool.shutdown();
}
}