java中使用线程池理解异步

理解异步的使用场景

异步会比同步更加快

例如我就拿抢票来举例子

抢票里面一般包含两个方法

抢票和下单

我们如果判断抢票成功后,那么我们可以向数据库里去下单了

但是如果我们的一个线程有两个这个方法,那我们就要等到这两个方法都执行完

但是其实我们如果判断抢到票,然后让它下单,这个线程就可以结束了,但是我们的线程要等到下单完成才结束,这样子会导致我们的接口返回有点慢

(大部分情况下是我们不需要使用异步的方法的返回值

所以这个时候我们就要使用到异步了

说到异步,我们其实可以使用消息队列mq,kafka等,也可以使用线程池

一般如果不是分布式项目的话直接使用线程池就行了,没必要使用到mq


我们来用一个测试类来模拟一下

弄一个阻塞队列和线程池

judge方法,判断是否抢票成功

create方法,抢票成功后创建订单 

我们的add方法,就是使用我们的judge方法和create方法

弄一个任务类连接Runnable接口

需要异步调用的时候把这个任务类扔进线程池就行了

我们的逻辑是,我们不断地从阻塞队列里来获取值,然后创建订单

PostConstruct初始化

我们初始化的时候就向线程池里面提交这个任务,这样子一开始就是线程池里的任务在执行了

这样子我们的这个方法当前线程只要判断是否抢票成功后,向阻塞队列添加完就结束了

有另一个异步的线程来执行下单操作

有两个不同的方法,我们来看看不同方法的使用时长是怎么样的


时间对比

异步的情况

结束时间是58秒

我们结束后订单还在创建,就说明是另一个线程在异步执行的

同步的情况

 

结束时间是68

一个是58,一个是68,这个速度差距非常大

ps: 我们这是执行1000次的时候的想过,亲测如果执行的次数少,例如10次,那么线程池异步的处理时间和正常代码的同步处理时间相差无几,但执行次数越多,相差越大


测试类代码

package com.example.admin;

import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.UUID;
import java.util.concurrent.*;

@SpringBootTest
@Slf4j
public class ThreadTest {


//阻塞队列
    BlockingQueue<String> blockingQueue=new ArrayBlockingQueue<>(1024*1024);

    //线程池
    public static final ExecutorService pool= Executors.newSingleThreadExecutor();


    //初始化的时候就开启线程任务
    @PostConstruct
    private void init(){
        pool.submit(new task());
    }


    //这个是我们的抢票
@Test
    void ticktes(){

    //add里面有两个方法judge和create
    add();


    }


    @Test
    void add(){
       long first = System.currentTimeMillis();
        for (int i = 0; i <1000 ; i++) {


            log.info("开始时间" + first);
            judge(UUID.randomUUID().toString());

//这个是使用线程池
            blockingQueue.add(UUID.randomUUID().toString());
            //这个是不使用线程池
//            create(UUID.randomUUID().toString());
        }
        log.info("结束时间"+(System.currentTimeMillis()-first));

    }

    //判断是否抢票成功
    String judge(String str)
    {
        return "用户"+str+"抢票成功,开始下单";

    }





    private class task implements Runnable{
        @Override
        public void run() {
while(true)
{
    try{
        //获取订单信息
        String id = blockingQueue.take();
        if(id!=null)
        //创建订单
        create(id);
    }
    catch (Exception e)
    {
log.error("处理异常信息",e);
    }

}

        }
    }

    //下单
    private void create(String id) {

        System.out.println("订单"+id+"创建成功");
        log.info("创建订单"+id+"成功");
    }



}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值