美文网首页
多线程并发同步业务场景与解决方案

多线程并发同步业务场景与解决方案

作者: vincky倩 | 来源:发表于2018-03-05 13:44 被阅读0次

    1)semaphore 信号量 (控制并发数)

    业务场景1:假如现在有10个人去同一家公司面试,但是只有3个面试官,那么同一时间只有2个人面试,当3个人中的任意一个面试结束之后,等待的7个人又会有一个人可以去面试。

    需求分析:人数=线程数     面试官=资源       正在面试=线程正在执行

                面试结束=线程执行结束           等待面试人数=线程阻塞

    解决方案:信号量 semaphore

    代码Demo:

    public class SemaphoreTest implements Runnable {

    private int num;

    private Semaphore semaphore;

    public SemaphoreTest(int num,Semaphore semaphore){

                this.num=num;

                this.semaphore=semaphore;

    }

    public void run() {

     try {

        semaphore.acquire();//获取信号量许可,才能进入

        System.out.println("面试者"+num+"进入房间……");

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

       System.out.println("面试者"+num+"交谈中……");

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

      System.out.println("面试者"+num+"离开房间……");

          semaphore.release();//释放信号量许可

     } catch (InterruptedException e) {

          e.printStackTrace();

    } }

    public static void main(String[] args) {

         final Semaphore s=new Semaphore(3);//并发数为3

         ExecutorService threadPool=Executors.newCachedThreadPool();//线程池

        for(int i=0;i<10;i++){

              threadPool.execute(new SemaphoreTest((i+1),s));

    }

        threadPool.shutdown();

    } }

    2)Cyclicbarrier  同步屏障(用于多线程计算数据,最后合并计算结果)

    业务场景2:公司周末组织去聚餐、首先各自从家里出发到聚餐地点,当所有人全部到齐之后才开始吃饭,如果未到齐,到的人就只能等待在那里,直到所有人都到达之后,才可以一起做事。

    案例代码:

    public class CyclicbarrierDemo {

    public static void main(String[] args) {

     final CyclicBarrier cb=new CyclicBarrier(3,new Runnable() {

     public void run() {

               System.out.println("吃饭前,一起做的事情"); } });

                ExecutorService threadPool=Executors.newCachedThreadPool();//线程池

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

                final int user=i+1;

                             Runnable r=new Runnable() {

                               public void run() {

                                    try {

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

                                           System.out.println(user+"到达聚餐地点,当前已有"+(cb.getNumberWaiting()+1)+"人到达");

                            cb.await();//等待,只有当线程都到达之后,才能往下走

                           if(user==1){ System.out.println("人员到齐"); }

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

                            System.out.println(user+"吃完饭,回家……");

     //dosometing

     } catch (Exception e) {

     e.printStackTrace(); } } };

     threadPool.execute(r);

     }

    threadPool.shutdown();

     } }

    3)Exchanger 线程之间交换数据

    public class ExchangerDemo {

    public static void main(String[] args) {

    final Exchangerexchanger=new Exchanger();

     ExecutorService threadPool=Executors.newCachedThreadPool();//线程池

    threadPool.execute(new Runnable() {

    public void run() { String sc="a";

     try {

    String js=exchanger.exchange(sc);//js=b

     } catch (InterruptedException e) { e.printStackTrace(); } } });

     threadPool.execute(new Runnable() {

     public void run() {

    String sc="b";

    try { String js=exchanger.exchange(sc);//js=a

     } catch (InterruptedException e) { e.printStackTrace(); } } }); } }

    执行后,连个线程的数据进行了交换。

    4)CountDownLatch 倒计时器

    业务场景4:有一个任务a,他需要等待其他几个任务(BCD)都执行完毕之后才能来执行这个任务。

    public static void main(String[] args) throws InterruptedException {

    final CountDownLatch latch=new CountDownLatch(3);

     new Thread(){

    public void run() {

     System.out.println("子任务B"+Thread.currentThread().getName()+"正在执行"); latch.countDown();//倒计时减一

    }; }.start();

    new Thread(){

     public void run() {

    System.out.println("子任务C"+Thread.currentThread().getName()+"正在执行"); latch.countDown();//倒计时减一

     }; }.start();

    new Thread(){

    public void run() {

    System.out.println("子任务D"+Thread.currentThread().getName()+"正在执行"); latch.countDown();//倒计时减一

     }; }.start();

    System.out.println("等待3个任务执行完毕,"+Thread.currentThread().getName()+"组任务开始执行。");

    latch.await();

    System.out.println("继续执行主任务!");

    }

    CountDownLatch 与Cyclicbarrier 的区别:

    1)共同点:都能够实现线程之间的等待。

    2)不同点:

    CountDownLatch :1)一般用于某个线程A等待其他若干线程执行完任务后,它才能执行。2)它是不能够重复用的。

    Cyclicbarrier :1)一般用于一组线程互相等待,然后这一组线程同时执行。2)它可以重复使用。

    相关文章

      网友评论

          本文标题:多线程并发同步业务场景与解决方案

          本文链接:https://www.haomeiwen.com/subject/eufhfftx.html