首页 > 文章列表 > 「Java多线程协作作业之信号同步的实现方式」

「Java多线程协作作业之信号同步的实现方式」

java
195 2023-04-30

Java多线程协作作业之信号同步怎么实现

    一、信号同步

    多线程很多时候是协作作业。比如4个线程对电商数据分季度统计,统计完成之后,再汇总。如何知道4个线程都执行完成呢,我们可以使用JDK1.5给我们提供的辅助类CountDownLatch(

    减少计数)、CyclicBarrier(循环栅栏)、Semaphore(信号灯)。

    二、基于时间维度

    1、CountDownLatch

    多少个协作线程就初始化CountDownLatch的构造参数是多少。

     public static void main(String[] args) throws InterruptedException {
    
            final int NUM=6;
    
            //定义总数量;
    
            CountDownLatch countDownLatch=new CountDownLatch(NUM);
    
            for (int i = 0; i < NUM; i++) {
    
                new Thread(()->{
    
                    System.out.println(Thread.currentThread().getName()+"线程,已执行!");
    
                    //减少计数
    
                    countDownLatch.countDown();
    
                },String.valueOf(i+1)).start();
    
            }
    
            //等待所有任务完成
    
            countDownLatch.await();
    
            System.out.println("所有线程任务已经执行完成!");
    
        }

    2、CyclicBarrier

    与减少计数类似

     public static void main(String[] args) {
    
            final int NUM = 6;
    
            //定义循环数量及循环完成后的任务(Runnable接口实现);
    
            CyclicBarrier cyclicBarrier = new CyclicBarrier(NUM, () -> {
    
                System.out.println("所有线程任务已经执行完成!");
    
            });
    
            for (int i = 0; i < NUM; i++) {
    
                new Thread(()->{
    
                    System.out.println(Thread.currentThread().getName()+"线程,已执行!");
    
                    try {
    
                        //等待点或障碍点,等待所有任务完成,
    
                        cyclicBarrier.await();
    
                    } catch (InterruptedException e) {
    
                        e.printStackTrace();
    
                    } catch (BrokenBarrierException e) {
    
                        e.printStackTrace();
    
                    }
    
                },String.valueOf(i+1)).start();
    
            }
    
        }

    三、基于信号维度

    Semaphore,线程与信号是m:n,其中m>=n。

    import java.util.Random;
    
    import java.util.concurrent.Semaphore;
    
    import java.util.concurrent.TimeUnit;
    
    /*信号灯
    
    * 6个线程,抢占三个信号
    
    * */
    
    public class SemaphoreDemo {
    
        public static void main(String[] args) {
    
            Semaphore semaphore=new Semaphore(3);
    
            for (int i = 0; i < 6; i++) {
    
                new Thread(()->{
    
                    try {
    
                        //获取信号
    
                        semaphore.acquire();
    
                        System.out.println("线程:"+Thread.currentThread().getName()+"----获取信号");
    
                        int time = new Random().nextInt(5);
    
                        System.out.println(("线程:"+Thread.currentThread().getName()+"----休眠"+time+"s!"));
    
                        TimeUnit.SECONDS.sleep(time);
    
                    } catch (InterruptedException e) {
    
                        e.printStackTrace();
    
                    }finally {
    
                    //    释放信号
    
                        System.out.println("线程:"+Thread.currentThread().getName()+"---释放信号");
    
                        semaphore.release();
    
                    }
    
                },String.valueOf(i+1)).start();
    
            }
    
        }
    
    }

    首先线程4、1、3获取到信号,线程1释放信号后,线程2获得信号。线程2、3释放信号后,线程5、6获得信号。