一篇教会你java使用线程池异步实战

一篇教会你java使用线程池异步实战

接口调用时间缩短



前言

提示:实战可用:

在当今高度并发的软件开发领域,有效地处理大量请求并提高系统的性能是至关重要的。Java提供了强大的线程池机制,使得异步编程成为提高应用程序效率的有力工具。本文将带领您深入了解Java线程池,并通过实际示例展示如何在项目中应用异步编程的最佳实践。

随着用户对实时性和响应速度的不断追求,传统的同步编程模型可能显得力不从心。线程池作为一种优秀的解决方案,不仅能够更有效地管理资源,还能够实现任务的并行执行,从而显著提高系统的并发处理能力。

在接下来的文章中,我们将深入探讨以下主题:

为什么使用线程池?
Java线程池的基本概念和工作原理。
如何通过线程池实现异步编程,提高系统的响应速度。
实际项目中的线程池应用场景与最佳实践。
无论您是初学者还是有一定经验的开发者,通过本文,您将获得在Java中使用线程池进行异步编程的实际技能,为您的项目提供更出色的性能和用户体验。

让我们一起探索Java线程池的奥秘,为您的应用程序注入新的活力!


提示:以下是本篇文章正文内容,下面案例可供参考

一、我们来开始吧?

我数据库里面有都少数据先看一下:

在这里插入图片描述
才一百多条 我这里会多个表进行查询 增加 修改

二、使用步骤

1.项目中的 resources

我们先新建一个
在这里插入图片描述
这个里面的内容呢 :

com.cn.blogboot.autoconfiguration.ThreadPoolAutoConfiguration
输入上面这个是我自己新建的一个class

代码如下(示例):

package com.cn.blogboot.autoconfiguration;

import com.cn.blogboot.properties.ThreadPoolExecutorProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Configuration
@EnableConfigurationProperties(ThreadPoolExecutorProperties.class)
@ConditionalOnProperty(prefix = "thread.pool", name = "enable", havingValue = "true")
public class ThreadPoolAutoConfiguration {

    @Bean
    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolExecutorProperties properties) {
        return new ThreadPoolExecutor(properties.getCorePoolSize(),
                properties.getMaximumPoolSize(),
                properties.getKeepAliveTime(),
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(10000),
                Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
    }
}

然后新建一个实体

package com.cn.blogboot.properties;

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;

@Getter
@Setter
@ConfigurationProperties(prefix = "thread.pool")
public class ThreadPoolExecutorProperties {

    /** 核心池大小 */
    private final Integer corePoolSize = 20;

    /** 最大池大小 */
    private final Integer maximumPoolSize = 200;

    /** 维持时间 */
    private final Long keepAliveTime = 15L;
}

然后yaml 里面进行配置 咋个配置呢

thread:
  pool:
    enable: true

开启就可以了

2.怎么使用

来咯来咯:看我操作我的一个案例
代码如下(示例):

package com.cn.blogboot.service.exchange.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cn.blogboot.constants.UserConstants;
import com.cn.blogboot.dto.ExchangeDot;
import com.cn.blogboot.exception.CustomException;
import com.cn.blogboot.mapper.ExchangeMapper;
import com.cn.blogboot.mapper.UserInfoMapper;
import com.cn.blogboot.model.UserModel;
import com.cn.blogboot.pojo.Exchange;
import com.cn.blogboot.pojo.UserInfo;
import com.cn.blogboot.service.IUserInfoService;
import com.cn.blogboot.service.exchange.IExchangeService;
import com.cn.blogboot.util.MinioClientConfig;
import com.cn.blogboot.util.RedisUtils;
import com.cn.blogboot.util.SimpleDateFormatUtils;
import com.cn.blogboot.vo.ExchangeVo;
import com.cn.blogboot.vo.HeadPortrait;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Service
@Transactional(rollbackFor = Exception.class)
@RequiredArgsConstructor
@Slf4j
public class ExchangeServiceImpl extends ServiceImpl<ExchangeMapper, Exchange> implements IExchangeService {
    private final ExchangeMapper exchangeMapper;
    private final UserInfoMapper userInfoMapper;
    private final MinioClientConfig minioClientConfig;

    /** 线程 */    // 这个一定要导入
    private final ThreadPoolExecutor thread;

    private final RedisUtils redisUtils;

    @Override
    public void useRedemptionCode(ExchangeDot dot) {
        Object object = redisUtils.hashGet(UserConstants.USER_INFO, StpUtil.getLoginId().toString());
        UserModel userModel = (UserModel) object;
        ExchangeVo vo = new ExchangeVo();
        //查询兑换码是否过期 & 已经使用
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            Optional<Exchange> exchange = Optional.ofNullable(exchangeMapper.selectOne(new LambdaUpdateWrapper<Exchange>()
                    .eq(Exchange::getRedemptionCode, dot.getRedemptionCode()).eq(Exchange::getStatus, 0)));
            exchange.ifPresentOrElse((e)->{
                final Date effectiveDate = e.getEffectiveDate();
                System.out.println("时间"+effectiveDate);
                if(SimpleDateFormatUtils.isExpired(effectiveDate)){
                    throw new CustomException("兑换码已过期",500);
                }
                vo.setExchange(e);
            }, () -> {
                throw new CustomException("兑换码不存在",500);
            });

            System.out.println("数据包"+vo);
        }, thread);

        // 修改   future.thenCompose((unused) -> CompletableFuture.runAsync(() -> {  等待上一个线程完成
        CompletableFuture<Void> useRedemptionCode = future.thenCompose((unused) -> CompletableFuture.runAsync(() -> {
            final UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getOpenId,userModel.getOpenId()));
            Exchange exchange = vo.getExchange();
            if(exchange!=null){
                Long treasuryCurrency = exchange.getTreasuryCurrency();
                System.out.println("库币"+treasuryCurrency);
                userInfoMapper.update(new UserInfo().setAiCoin(userInfo.getAiCoin()+treasuryCurrency),new LambdaUpdateWrapper<UserInfo>()
                        .eq(UserInfo::getOpenId,userModel.getOpenId()));
            }
        }, thread));

        //修改兑换码状态
        CompletableFuture<Void> updateRedemptionCode = CompletableFuture.runAsync(() -> {
                 exchangeMapper.update(new Exchange().setStatus(1L),new LambdaUpdateWrapper<Exchange>()
                               .eq(Exchange::getRedemptionCode,dot.getRedemptionCode()));
        }, thread);

        try {
            //堵塞任务执行
            CompletableFuture<Void> allOf = CompletableFuture.allOf(future, useRedemptionCode, updateRedemptionCode);
            allOf.get(5, TimeUnit.SECONDS);
        } catch (Exception e) {
             // 下面这个是我自己的返回业务
            String customExceptionMessage="";
            String exceptionString = e.getMessage();
            String[] parts = exceptionString.split("[=,)]");
            if (parts.length >= 4) {
                String message = parts[1].trim();
                int code = Integer.parseInt(parts[3].trim());
                CustomException customException = new CustomException(message, code);
                 customExceptionMessage = customException.getMessage();

            }
            throw new CustomException(customExceptionMessage,500);
        }

    }
}

我上面是查询兑换码 然后修改然后 在进行使用 返回速度
在这里插入图片描述

CompletableFuture 是 Java 8 引入的一个类,用于支持异步编程和并发操作。它提供了一种方便的方式来处理异步任务的结果,以及对多个异步任务的组合和组织。CompletableFuture 类实现了 Future 接口

可以增加删除查询修改 异步执行 提高接口的速度 ,我这里写了一个案例
更多复杂业务 可以自行对照写
直接拉满~~~~

总结

这个可是很实用的,自测 调用超级快,更多优化实用的东西等你来

  • 26
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杰哥力挽狂澜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值