JDK7对并发编程提供了更好的支持,包括ThreadLocalRandom、ForkJoinPool、TransferQueue以及本文要讲述的Phaser。
JDK5中引入了CyclicBarrier和CountDownLatch这两个并发控制类,而JDK7中引入的Phaser按照官方的说法是提供了一个功能类似但是更加灵活的实现。接下来我们研究一下Phaser与两个位辈到底有哪些类似,同时带来了哪些灵活性。
CyclicBarrier和CountDownLatch
在使用CyclicBarrier时,需要创建一个CyclicBarrier对象,构造函数需要一个整数作为参数,这个参数是一个“目标”,在CyclicBarrier对象创建后,内部会有一个计数器,初始值为0,CyclicBarrier对象的await方法没被调用一次,这个计数器就会加1,一旦这个计数器的值达到设定的“目标”,所有被CyclicBarrier.await阻塞住的线程都会继续执行。这个目标是固定的,一旦设定便不能修改。
举一个形象的例子,假设有5个人爬山,他们要爬到山顶,等到5个人到期了在同时出发下山,那么我们要在山顶设定一个“目标”,同时还有一个计数器,这个目标就是5,每到山顶一个人,这个人就要等待,同时计数器加1,等到5个人到齐了,也就是计数器达到了这个“目标”,所有等待的人就开始下山了。
使用CountDownLatch时,需要创建一个CountDownLatch对象,构造函数也需要一个整数作为参数,可以把这个参数想象成一个倒计时器,CountDownLatch对象本身是一个发令枪,所有调用CountDownLatch.await方法的线程都会等待发令枪的指令,一旦倒计时器为0,这些线程同时开始执行,而CountDownLatch.countDown方法就是为倒计时器减1。
CyclicBarrier和CountDownLatch的共同点都是有一个目标和一个计数器,等到计数器达到目标后,所有阻塞的线程都将继续执行。他们的不同点是CyclicBarrier.await在等待的同时还修改计数器,而CountDownLatch.await只负责等待,CountDownLatch.countDown才修改计数器,这是他们最本质的区别(千万不要告诉我他们的区别是一个加1一个减1!这就像数数,从1数到10和从10数到1都是数10个数,没有区别的)。
接下来我们分析一下JDK7新加入的Phaser。
Phaser
Phaser同时包含CyclicBarrier和CountDownLatch两个类的功能。Phaser的arrive方法将将计数器加1,awaitAdvance将线程阻塞,直到计数器达到目标,这两个方法与CountDownLatch的countDown和await方法相对应;Phaser的arriveAndAwaitAdvance方法将计数器加1的同时将线程阻塞,直到计数器达到目标后继续执行,这个方法对应CyclicBarrier的await方法。
除了包含以上两个类的功能外,Phaser还提供了更大的灵活性。CyclicBarrier和CountdownLatch在构造函数指定目标后就无法修改,而Phaser提供了register和deregister方法可以对目标进行动态修改。
以下提供一组例子,第一个例子展示了上文中提到的Phaser的方法,第二第三个例子展示了Phaser适用的两个场景,尤其是第三个,这个场景在没有Phaser是比较不容易实现的:
package com.lunarever.study.java7test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Phaser;
import java.util.logging.Level;
import java.util.logging.Logger;
public class PhraseTest {
public static void main(String[] args) throws Exception {
demo1();
demo2();
demo3();
}
public static void demo1() throws Exception {
final Phaser phaser = new Phaser(3) {
@Override
protected boolean onAdvance(int phase, int registeredParties) {
System.out.printf("---> run here: onAdvance --> phase=%d, parties=%d%n", phase, registeredParties);
return super.onAdvance(phase, registeredParties);
}
};
new Thread() {
@Override
public void run() {
System.out.println("---> run here: awaitAdvance 0 start");
phaser.awaitAdvance(0);
System.out.println("---> run here: awaitAdvance 0 end");
}
}.start();
new Thread() {
@Override
public void run() {
System.out.println("---> run here: awaitAdvance 1 start");
phaser.awaitAdvance(1);
System.out.println("---> run here: awaitAdvance 1 end");
}
}.start();
new Thread() {
@Override
public void run() {
System.out.println("---> run here: arriveAndAwaitAdvance start");
phaser.arriveAndAwaitAdvance();
System.out.println("---> run here: arriveAndAwaitAdvance end");
}
}.start();
Thread.sleep(200);
System.out.println("---> arriveAndDeregister 1");
System.out.println("---> arriveAndDeregister 1 -> " + phaser.arriveAndDeregister());
Thread.sleep(200);
System.out.println("---> arrive 1");
System.out.println("---> arrive 1 -> " + phaser.arrive());
Thread.sleep(200);
System.out.println("---> register 1");
phaser.register();
Thread.sleep(200);
System.out.println("---> arrive 2");
System.out.println("---> arrive 2 -> " + phaser.arrive());
Thread.sleep(200);
System.out.println("---> arrive 3");
System.out.println("---> arrive 3 -> " + phaser.arrive());
Thread.sleep(200);
System.out.println("---> arrive 4");
System.out.println("---> arrive 4 -> " + phaser.arrive());
Thread.sleep(200);
System.out.println("---> arrive 5");
System.out.println("---> arrive 5 -> " + phaser.arrive());
Thread.sleep(200);
System.out.println("---> arrive 6");
System.out.println("---> arrive 6 -> " + phaser.arrive());
Thread.sleep(200);
System.out.println("---> arrive 7");
System.out.println("---> arrive 7 -> " + phaser.arrive());
Thread.sleep(200);
System.out.println("---> arrive 8");
System.out.println("---> arrive 8 -> " + phaser.arrive());
Thread.sleep(200);
System.out.println("---> arrive 9");
System.out.println("---> arrive 9 -> " + phaser.arrive());
}
public static void demo2() {
final List<Runnable> tasks = new ArrayList<Runnable>();
for (int i = 0; i < 3; i++) {
final int counter = i;
tasks.add(new Runnable() {
@Override
public void run() {
System.out.println("---> " + counter);
try {
Thread.sleep(200);
} catch (InterruptedException ex) {
Logger.getLogger(PhraseTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
final Phaser phaser = new Phaser(1); // "1" to register self
// create and start threads
for (final Runnable task : tasks) {
phaser.register();
new Thread() {
@Override
public void run() {
phaser.arriveAndAwaitAdvance(); // await all creation
task.run();
}
}.start();
}
phaser.arriveAndDeregister(); // allow threads to start and deregister self
}
public static void demo3() {
final List<Runnable> tasks = new ArrayList<Runnable>();
for (int i = 0; i < 3; i++) {
final int counter = i;
tasks.add(new Runnable() {
@Override
public void run() {
System.out.println("---> " + counter);
try {
Thread.sleep(200);
} catch (InterruptedException ex) {
Logger.getLogger(PhraseTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
final Phaser phaser = new Phaser() {
@Override
protected boolean onAdvance(int phase, int registeredParties) {
return phase >= 5 || registeredParties == 0;
}
};
phaser.register();
for (final Runnable task : tasks) {
phaser.register();
new Thread() {
@Override
public void run() {
do {
task.run();
phaser.arriveAndAwaitAdvance();
} while (!phaser.isTerminated());
}
}.start();
}
phaser.arriveAndDeregister(); // deregister self, don't wait
}
}
分享到:
相关推荐
这份"Java JDK 6学习笔记——ppt简体版"提供了关于这个关键版本的详细教程,适合初学者和有一定经验的开发者来深入理解Java编程。 首先,我们要了解Java JDK是什么。Java Development Kit,简称JDK,是Oracle公司...
总的来说,“Java JDK 6学习笔记——ppt简体版”全面介绍了Java编程语言的基础知识和JDK 6的关键特性,结合配套的代码示例,是系统学习和掌握Java开发的宝贵资料。无论你是Java初学者还是寻求提升的老手,都能从中...
并发工具类库(java.util.concurrent)在JDK 6中得到了进一步完善,如CountDownLatch、CyclicBarrier和Phaser等,为多线程编程提供了强大的工具。 10. **日志框架API** JDK 6引入了JSR 47,即Java Management ...
Linux安装JDK指南 Linux安装JDK是开发者和系统管理员最常见的任务之一。正确安装JDK对于Java应用程序的运行至关重要。本文将指导您如何在Linux系统上安装JDK。 一、解压JDK 安装JDK的第一步是解压缩JDK安装包。...
Java JDK 6学习笔记——ppt简体版 第20章.ppt
Java JDK 6学习笔记——ppt简体版 第19章.ppt
Java JDK 6学习笔记——ppt简体版 第18章.ppt
高并发编程第三阶段35讲 Phaser工具的实战案例使用第一部分_.mp4 高并发编程第三阶段36讲 Phaser工具的实战案例使用第二部分_.mp4 高并发编程第三阶段37讲 Phaser工具的实战案例使用第三部分_.mp4 高并发...
**JDK 6学习笔记——PPT简体版** Java Development Kit(JDK)是Java编程语言的核心组件,它提供了开发和运行Java应用程序所需的工具和环境。JDK 6是Oracle公司发布的一个重要版本,为开发者带来了许多改进和新特性...
Java JDK 6学习笔记——PPT简体版是针对初学者和有经验的开发者们的一份宝贵资源,它深入浅出地介绍了Java编程语言的核心概念和技术。这份资料以PPT的形式呈现,使得学习过程更加直观易懂,同时包含了课程中的源代码...
这本书由拥有丰富经验的JDK并发大师及业界专家撰写,详细解释了Java 5.0和Java 6中引入的新并发功能,以及并发编程的一般性概念。 并发编程已经成为现代计算机科学不可或缺的一部分,尤其是在Java这样的多线程支持...
11. **并发编程改进**:引入了java.util.concurrent包,提供了线程安全的数据结构和并发工具类,如ExecutorService、Semaphore等,使得多线程编程更加高效和易用。 12. **NIO(非阻塞I/O)**:Java 5.0引入了NIO...
JDK 6.0 安装手册 JDK 6.0 安装手册是一份详细的安装指南,适用于在不同的操作系统上安装 JDK 6.0。该手册涵盖了 Windows、Linux 和 Aix 操作系统下的安装步骤、环境配置和安装验证。 JDK 6.0 概述 JDK 6.0 是 ...