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

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)它可以重复使用。

你可能感兴趣的:(多线程并发同步业务场景与解决方案)