多线程并发提升性能的三种实现方式Future、CountDownLatch、Semaphore

前言

我们在应用开发时往往会涉及到当主流程需要执行多个子流程导致运行效率较低的情况。
此时如果多个子流程之间彼此不关联时,可以使用多线程来优化代码。

如主流程A,依次执行子流程a、b、c时,总时间为a+b+c,但是如果我们使用多线程分开执行a、b、c时,理论上总时间可以控制为其中执行最大的时间,这样可以大大节省时间

本文介绍实现上述功能的三种方式

线程池Future实现方式

代码实现:

public static void future() throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        Future f1 = executorService.submit(()->{
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程1执行");
        });
        Future f2 = executorService.submit(()->{
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程2执行");
        });

        // 当线程1和线程2都完成后再执行后面的逻辑
        f1.get(); // 阻塞,知道f1的线程执行完成
        f2.get(); // 阻塞,知道f2的线程执行完成
        System.out.println("线程1和线程2都执行完成了");
    }

计数器CountDownLatch实现方式

代码实现:

public static void countDownLatch() throws InterruptedException {
        // 定义一个计数器
        CountDownLatch countDownLatch = new CountDownLatch(2);
        new Thread(() -> {
            try {
                Thread.sleep(2000);
                System.out.println("线程1执行");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                countDownLatch.countDown();
            }
        }).start();
        new Thread(() -> {
            try {
                Thread.sleep(2000);
                System.out.println("线程2执行");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                countDownLatch.countDown();
            }
        }).start();
        // 阻塞,直到计数器为0,这里根据业务可以加超时时间,避免出现异常情况,
        // 需要注意避免某个线程报错了导致没有调用countDown,即最好在线程里面finally里面执行
        long start = System.currentTimeMillis();
        countDownLatch.await(3000,TimeUnit.MILLISECONDS);
        long end = System.currentTimeMillis();
        if(end - start > 3000) {
            System.out.println("超时了,业务停止");
        } else {
            System.out.println("线程1和线程2都执行完成了");
        }

    }

信号量Semaphore实现方式

代码实现:

  public static void semaphore() throws InterruptedException {
        int threadCount = 2;
        Semaphore semaphore = new Semaphore(-threadCount+1);
        new Thread(() -> {
            try {
                Thread.sleep(2000);
                System.out.println("线程1执行");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                // 释放1个限号量
                semaphore.release();
            }
        }).start();
        new Thread(() -> {
            try {
                Thread.sleep(2000);
                System.out.println("线程2执行");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                // 释放1个限号量
                semaphore.release();
            }
        }).start();
        // 阻塞,知道semaphore的值为1以上,即2个线程都释放了一个信号量,信号量才为1,
        semaphore.acquire();
        System.out.println("线程1和线程2执行完成");
    }
  public static void main(String[] args) throws InterruptedException, ExecutionException {
        // 让两个线程完成后再执行主线程代码

        // 方式1,基于线程池Future
        future();

        // 方式2,基于计数器CountDownLatch
        countDownLatch();

        // 访视3,基于信号量Semaphore
        semaphore();

    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值