多线程12-CyclicBarrier、CountDownLatch、Exchanger

1.CyclicBarrier 

     表示大家彼此等待,大家集合好后才开始出发,分散活动后又在指定地点集合碰面

package org.lkl.thead.foo;



import java.util.concurrent.CyclicBarrier;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;



/**

 * 表示大家彼此等待,大家集合好后才开始出发,分散活动后又在指定地点集合碰面

 */

public class CyclicBarrierFoo {

     public static void main(String[] args) {

      ExecutorService threadPool =     Executors.newCachedThreadPool() ;

      

      final CyclicBarrier cyclicBarrier = new CyclicBarrier(3) ;  //表示有3个线程需要彼此等待  都执行到 cyclicBarrier.await() ;以后才继续执行 

      

      for(int i=1 ;i<=3 ;i++){

          Runnable r = new Runnable() {

            @Override

            public void run() {

                

                

                try {

                    Thread.sleep((long)(Math.random()*10000));

                    System.out.println("线程" + Thread.currentThread().getName() + 

                            "即将到达集合地点1,当前已有" + (cyclicBarrier.getNumberWaiting()+1) + "个已经到达," + (cyclicBarrier.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));                        

                    

                    cyclicBarrier.await() ;  //类似于集合点

                    

                    

                    Thread.sleep((long)(Math.random()*10000));

                    System.out.println("线程" + Thread.currentThread().getName() + 

                            "即将到达集合地点2,当前已有" + (cyclicBarrier.getNumberWaiting()+1) + "个已经到达," + (cyclicBarrier.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));                        

                    

                    cyclicBarrier.await() ;  //类似于集合点

                    

                    Thread.sleep((long)(Math.random()*10000));

                    System.out.println("线程" + Thread.currentThread().getName() + 

                            "即将到达集合地点3,当前已有" + (cyclicBarrier.getNumberWaiting()+1) + "个已经到达," + (cyclicBarrier.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));                        

                    

                    cyclicBarrier.await() ;  //类似于集合点

                    

                    

                    

                } catch (Exception e) {

                    e.printStackTrace();

                } 

            }

        };

        threadPool.execute(r) ;

      }

    }

}

 

允许结果如下: 

线程pool-1-thread-3即将到达集合地点1,当前已有1个已经到达,正在等候

线程pool-1-thread-1即将到达集合地点1,当前已有2个已经到达,正在等候

线程pool-1-thread-2即将到达集合地点1,当前已有3个已经到达,都到齐了,继续走啊

线程pool-1-thread-3即将到达集合地点2,当前已有1个已经到达,正在等候

线程pool-1-thread-1即将到达集合地点2,当前已有2个已经到达,正在等候

线程pool-1-thread-2即将到达集合地点2,当前已有3个已经到达,都到齐了,继续走啊

线程pool-1-thread-2即将到达集合地点3,当前已有1个已经到达,正在等候

线程pool-1-thread-1即将到达集合地点3,当前已有2个已经到达,正在等候

线程pool-1-thread-3即将到达集合地点3,当前已有3个已经到达,都到齐了,继续走啊

 

2. CountdownLatchFoo

        犹如倒计时计数器,调用CountDownLatch对象的countDown方法就将计数器减1,当计数到达0时,则所有等待者或单个等待者开始执行

可以实现一个人(也可以是多个人)等待其他所有人都来通知他,这犹如一个计划需要多个领导都签字后才能继续向下实施。还可以实现一个人通知多个人的效果,类似裁判一声口令,运动员同时开始奔跑

 

package org.lkl.thead.foo;



import java.util.concurrent.CountDownLatch;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;



public class CountdownLatchFoo {

  

    /**

     * 实现代码: 

     *  主线程发布命令  然后开启三个线程在等待主线程发布的命令 ,

     *  当子线程接收命令以后 传递一个回调的命令给主线程  然后主线程接收回调命令

     */

    

    

    public static void main(String[] args) {

        final CountDownLatch orderLatch = new CountDownLatch(1) ; //表示从1 开始倒计时

        final CountDownLatch answerLatch = new CountDownLatch(3) ; //表示从3开始倒计时

        

        ExecutorService threadPool = Executors.newCachedThreadPool() ;

        for(int i=1 ;i<=3 ;i++){

            Runnable runnable = new Runnable() {

                @Override

                public void run() {

                    System.out.println("线程"+Thread.currentThread().getName()+"准备接收数据.");

                    try {

                        orderLatch.await() ; //表示等待主线程发布命令,没有接收到命令就会一致等待下去

                    } catch (InterruptedException e) {

                        e.printStackTrace();

                    }

                    

                    

                    System.out.println("线程"+Thread.currentThread().getName()+" 接收到命令 ");  //只有接收到命令 程序才会从await方法中执行下来

                    

                    //给主线程回调命令

                    

                    System.out.println("线程"+Thread.currentThread().getName()+" 准备向主线程回调. "); 

                    try {

                        Thread.sleep((long)(Math.random()*10000));

                    } catch (InterruptedException e) {

                        e.printStackTrace();

                    }    

                    answerLatch.countDown() ; //表示发布命令  从3开始倒计时   前期主线程会被answerLatch.await() 方法拦截下来 等待回调

                    

                    System.out.println("线程"+Thread.currentThread().getName()+" 已经向主线程回调. "); 

                    

                    

                }

            };

            threadPool.execute(runnable) ;

        }

        

        //主线程

         

        try {

            Thread.sleep((long)(Math.random()*10000));

            System.out.println("主线程"+Thread.currentThread().getName()+"准备向三个子线程发送命令.");

            orderLatch.countDown() ; //向三个子线程发送命令

            System.out.println("主线程"+Thread.currentThread().getName()+"已经向三个子线程发送命令.");

            

            System.out.println("主线程"+Thread.currentThread().getName()+"等待三个子线程的回调.");

            answerLatch.await() ;

            

            System.out.println("主线程"+Thread.currentThread().getName()+"已经收到三个子线程的回调.");

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

}

 

  运行结果: 

线程pool-1-thread-1准备接收数据.

线程pool-1-thread-2准备接收数据.

线程pool-1-thread-3准备接收数据.

主线程main准备向三个子线程发送命令.

线程pool-1-thread-2 接收到命令 

线程pool-1-thread-2 准备向主线程回调. 

主线程main已经向三个子线程发送命令.

主线程main等待三个子线程的回调.

线程pool-1-thread-3 接收到命令 

线程pool-1-thread-3 准备向主线程回调. 

线程pool-1-thread-1 接收到命令 

线程pool-1-thread-1 准备向主线程回调. 

线程pool-1-thread-1 已经向主线程回调. 

线程pool-1-thread-2 已经向主线程回调. 

线程pool-1-thread-3 已经向主线程回调. 

主线程main已经收到三个子线程的回调.

 

 

3. Exchanger

用于实现两个人之间的数据交换,每个人在完成一定的事务后想与对方交换数据,第一个先拿出数据的人将一直等待第二个人拿着数据到来时,才能彼此交换数据

package org.lkl.thead.foo;



import java.util.concurrent.Exchanger;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;



public class ExchangerFoo {



    public static void main(String[] args) {

     ExecutorService threadPool =    Executors.newCachedThreadPool() ;

     final Exchanger<String> change = new Exchanger<String>() ;

     threadPool.execute(new Runnable() {

        

        @Override

        public void run() {

            try {

                String myData = "zhangsan" ;

                System.out.println("线程" + Thread.currentThread().getName() + 

                        "正在把数据" + myData +"换出去");

                String mychange = change.exchange(myData) ;

                Thread.sleep((long)(Math.random()*10000));

                System.out.println("线程" + Thread.currentThread().getName() + 

                        "换回来的数据为" + mychange);

            } catch (Exception e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

            

        }

    }) ;

     

     

     threadPool.execute(new Runnable() {

         

         @Override

         public void run() {

             try {

                 String myData = "lisi" ;

                 System.out.println("线程" + Thread.currentThread().getName() + 

                         "正在把数据" + myData +"换出去");

                 String mychange = change.exchange(myData) ;

                 Thread.sleep((long)(Math.random()*10000));

                 System.out.println("线程" + Thread.currentThread().getName() + 

                         "换回来的数据为" + mychange);

             } catch (Exception e) {

                 // TODO Auto-generated catch block

                 e.printStackTrace();

             }

             

         }

     }) ;

     

     

    }

}

 

运行结果:

线程pool-1-thread-2正在把数据lisi换出去

线程pool-1-thread-1正在把数据zhangsan换出去

线程pool-1-thread-2换回来的数据为zhangsan

线程pool-1-thread-1换回来的数据为lisi

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(CountDownLatch)