`
yaofeng928
  • 浏览: 7389 次
  • 性别: Icon_minigender_1
  • 来自: 沈阳
社区版块
存档分类
最新评论

探索JDK7的并发编程——PHASER

    博客分类:
  • Java
阅读更多
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
     }
}

7
13
分享到:
评论
1 楼 deepnighttwo 2011-08-10  
没装Java7,没试用,但是看文章写的还不错,挺清晰明了的,为啥这么多人踩捏。。。

相关推荐

    Java JDK 6学习笔记——ppt简体版.rar

    这份"Java JDK 6学习笔记——ppt简体版"提供了关于这个关键版本的详细教程,适合初学者和有一定经验的开发者来深入理解Java编程。 首先,我们要了解Java JDK是什么。Java Development Kit,简称JDK,是Oracle公司...

    Java JDK 6学习笔记——ppt简体版附课本代码

    总的来说,“Java JDK 6学习笔记——ppt简体版”全面介绍了Java编程语言的基础知识和JDK 6的关键特性,结合配套的代码示例,是系统学习和掌握Java开发的宝贵资料。无论你是Java初学者还是寻求提升的老手,都能从中...

    Java JDK 6学习笔记——ppt简体版

    并发工具类库(java.util.concurrent)在JDK 6中得到了进一步完善,如CountDownLatch、CyclicBarrier和Phaser等,为多线程编程提供了强大的工具。 10. **日志框架API** JDK 6引入了JSR 47,即Java Management ...

    linux安装jdk(csdn)————程序.pdf

    Linux安装JDK指南 Linux安装JDK是开发者和系统管理员最常见的任务之一。正确安装JDK对于Java应用程序的运行至关重要。本文将指导您如何在Linux系统上安装JDK。 一、解压JDK 安装JDK的第一步是解压缩JDK安装包。...

    Java JDK 6学习笔记——ppt简体版 第20章.ppt

    Java JDK 6学习笔记——ppt简体版 第20章.ppt

    Java JDK 6学习笔记——ppt简体版 第19章.ppt

    Java JDK 6学习笔记——ppt简体版 第19章.ppt

    Java JDK 6学习笔记——ppt简体版 第18章.ppt

    Java JDK 6学习笔记——ppt简体版 第18章.ppt

    汪文君高并发编程实战视频资源下载.txt

     高并发编程第三阶段35讲 Phaser工具的实战案例使用第一部分_.mp4  高并发编程第三阶段36讲 Phaser工具的实战案例使用第二部分_.mp4  高并发编程第三阶段37讲 Phaser工具的实战案例使用第三部分_.mp4  高并发...

    JDK 6学习笔记——PPT简体版

    **JDK 6学习笔记——PPT简体版** Java Development Kit(JDK)是Java编程语言的核心组件,它提供了开发和运行Java应用程序所需的工具和环境。JDK 6是Oracle公司发布的一个重要版本,为开发者带来了许多改进和新特性...

    Java JDK 6学习笔记——ppt

    Java JDK 6学习笔记——PPT简体版是针对初学者和有经验的开发者们的一份宝贵资源,它深入浅出地介绍了Java编程语言的核心概念和技术。这份资料以PPT的形式呈现,使得学习过程更加直观易懂,同时包含了课程中的源代码...

    Java并发编程实战华章专业开发者书库 (Tim Peierls 等 美Brian Goetz).pdf

    这本书由拥有丰富经验的JDK并发大师及业界专家撰写,详细解释了Java 5.0和Java 6中引入的新并发功能,以及并发编程的一般性概念。 并发编程已经成为现代计算机科学不可或缺的一部分,尤其是在Java这样的多线程支持...

    java jdk5.0学习笔记——良葛格

    11. **并发编程改进**:引入了java.util.concurrent包,提供了线程安全的数据结构和并发工具类,如ExecutorService、Semaphore等,使得多线程编程更加高效和易用。 12. **NIO(非阻塞I/O)**:Java 5.0引入了NIO...

    JDK 6.0安装手册——jdk,linux,aix,widow,Solarise.docx

    JDK 6.0 安装手册 JDK 6.0 安装手册是一份详细的安装指南,适用于在不同的操作系统上安装 JDK 6.0。该手册涵盖了 Windows、Linux 和 Aix 操作系统下的安装步骤、环境配置和安装验证。 JDK 6.0 概述 JDK 6.0 是 ...

Global site tag (gtag.js) - Google Analytics