Java5新增的同步工具

java.util.concurrent包中的同步工具

CyclicBarrier

一个同步辅助类,它允许 一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier.

  • 示例程序:

/*
问题:有三个工作者,有两个任务A,B,要求三个工作者反复工作=>完成A任务后,才可以开始B任务,都完成B任务后,一轮结束.
要求在三轮后结束工作.
 */
public class CyclicBarrierDemo1 {
      public static void main(String[] args) {
          CyclicBarrierDemo1 demo= new CyclicBarrierDemo1();
           int n =3;
           //线程池
          ExecutorService e =Executors.newFixedThreadPool( n);
           //监视器
          Watch watch= demo. new Watch(3);
           //定义n个线程等待的屏障
          CyclicBarrier barrier= new CyclicBarrier(n ,watch );
           for (int i =0;i <n ;i ++){
               e.execute( demo. new Worker(barrier ,watch ));
          }
           e.shutdown();
     }
      /*
      * 工作者,当所有的工作者一次完成A,并且B后,监视器将会返回信号结束工作.
      */
      class Worker implements Runnable{
           private Watch watch ;
           private CyclicBarrier barrier ;
           public Worker(CyclicBarrier barrier ,Watch w ){
               this .watch =w ;
               this .barrier =barrier ;
          }
           public void taskA(){
               System. out .println(Thread.currentThread().getName()+ "已完成任务A,等待" +barrier .getNumberWaiting());
          }
           public void taskB(){
               System. out .println(Thread.currentThread().getName()+ "已完成任务B,等待" +barrier .getNumberWaiting());
          }
           public void end(){
               System. out .println(Thread.currentThread().getName()+ "END" );
          }
           public void run(){
               while (!watch .done()){
                    try {
                        Thread. sleep(( long) (Math.random()*10000));
                        taskA();
                         barrier.await();
                        Thread. sleep(( long) (Math.random()*10000));
                        taskB();
                         barrier.await();
                   } catch (InterruptedException e ){
                         e.printStackTrace();
                   } catch (BrokenBarrierException e ) {
                         e.printStackTrace();
                   }
              }
              end();
          }
     }
      /*
      * 构造函数接收一个参数,表示任务轮作的次数
      */
      class Watch implements Runnable{
           private boolean done = false;
           private int num =0;
           private int m =0;
           public Watch(int num ){
               this .num =num ;
          }
           public void run(){
               if (++m %2==0){
                   System. out .println("第" +(m /2)+"轮任务结束" );
              }
               if (m /2==num )done = true;
          }
           public boolean done(){ return done;}
     }
}

CountDownLatch

一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待

+示例程序1



/*
 * 问题:模拟赛跑程式:有五个运动员,裁判员吹哨后,运动员开始冲向终点,所有运动员到达终点后,裁判员宣布比赛结束.
 */
public class CountDownLatchDemo1 {
      public static void main(String[] args) throws InterruptedException {
          CountDownLatchDemo1  demo= new CountDownLatchDemo1 ();
           int n =5;
          ExecutorService e =Executors.newFixedThreadPool( n);
          CountDownLatch startCount =new CountDownLatch(1);
          CountDownLatch doneCount =new CountDownLatch( n);
           for (int i =0;i <n ;i ++){
               e.execute( demo. new Sporter(startCount ,doneCount ));
          }
           e.shutdown();
          Thread. sleep(2000);
          System. out .println("裁判员说:比赛开始" );
           startCount .countDown();
           doneCount .await();
          System. out .println("裁判员说:比赛结束" );
     }
      class Sporter implements Runnable{
           private CountDownLatch startCount ;
           private CountDownLatch doneCount ;
           public Sporter(CountDownLatch startCount ,CountDownLatch doneCount ){
               this .startCount =startCount ;
               this .doneCount =doneCount ;
          }
           public void run(){
               while (true ){
                    try {
                        prepare();
                         startCount .await();
                        Thread. sleep(( long) (Math.random()*10000));
                        running();
                         doneCount .countDown();
                         break ;
                   } catch (InterruptedException e ) {
                         e.printStackTrace();
                   }
              }
          }
           public void prepare(){
               System. out .println(Thread.currentThread()+ "准备!" );
          }
           public void running(){
               System. out .println(Thread.currentThread()+ "到达终点!" );
          }
     }
}
  • 示例程序2

/*
 * 问题:模拟电脑生产(启发程式)
 * 生产一台电脑,可以按照组装的形式,先将各部分生产,在组装到一起.使用CountDoenLatch模拟生产过程.
 * 现在假设电脑有5个组件,5个组件生产完成后,开始组装.
 */
public class CountDownLatchDemo2 {
      public static void main(String[] args) throws InterruptedException {
          CountDownLatchDemo2  demo= new CountDownLatchDemo2 ();
           int n =5;
          ExecutorService e =Executors.newFixedThreadPool( n);
          CountDownLatch startCount =new CountDownLatch( n);
           for (int i =1;i <=n ;i ++){
               e.execute( demo. new Producer(startCount ,i ));
          }
           e.shutdown();
           startCount .await();
          System. out .println("开始组装!" );
     }
      class Producer implements Runnable{
           private CountDownLatch startCount ;
           private Object component ;
           public Producer(CountDownLatch startCount ,Object component ){
               this .startCount =startCount ;
               this .component =component ;
          }
           public void run(){
               while (true ){
                    try {
                        Thread. sleep(( long) (Math.random()*10000));
                        production();
                         startCount .countDown();
                         break ;
                   } catch (InterruptedException e ) {
                         e.printStackTrace();
                   }
              }
          }
           private void production() {
              System. out .println("组件" +component +"完成!" );
          }

     }
}

CyclicBarrier比较CountDownLatch

两者都使用了计数器,CyclicBarrier增加计数,当线程调用CyclicBarrier.await()时,计数器值增加,
如果计数器值小于规定数值,当前线程将一直处于等待.直到满足才继续.CountDownLatch减小计数,当线程调用CountDownLatch.await()时,当前线程将处于等待状态,直到计数器值为0,调用它的countDown()方法可以使计数器值减小1.

Exchanger

可以在对中对元素进行配对和交换的线程的同步点。每个线程将条目上的某个方法呈现给 exchange 方法,与伙伴线程进行匹配,并且在返回时接收其伙伴的对象。Exchanger 可能被视为 SynchronousQueue 的双向形式。Exchanger 可能在应用程序(比如遗传算法和管道设计)中很有用.

  • 示例程序

/*
 * Exchange<E> 使用示例:
 * 问题: 交换两个线程的数据
 */
public class ExchangeDemo1 {

      public static void main(String[] args) {
          ExchangeDemo1 e= new ExchangeDemo1();
           e.start();
     }
     Exchanger<Integer> exchanger =new Exchanger<>();
     ExecutorService service = Executors.newCachedThreadPool();
      class Changer implements Runnable{
           public void run(){
               while (true ){
                    try {
                        Integer data= new Random().nextInt(900)+100;
                        Thread. sleep(1000);
                         //拿出数据,等待交换
                        Integer dx =exchanger .exchange( data);
                        System. out .println(data +"<=>" +dx );
                   } catch (InterruptedException e ) {
                         e.printStackTrace();
                   }
              }
          }
     }
      public void start(){
           for (int i =0;i <3;i ++){
               service.execute( new Changer());
          }
           service.shutdown();
     }
}

猜你喜欢

转载自blog.csdn.net/mydream20130314/article/details/44998187