springboot 中多线程+线程池如何实现

1.  概念理解:

 多线程和异步调用之前一直不理解有什么区别,发现,这两个是一件事情的不同角度,多线程是方法,异步是目的

在springboot 可以通过注解@Async 搞定。

线程池:线程池引入的目的是为了解决:多次使用线程意味着,我们需要多次创建并销毁线程。而创建并销毁线程的过程势必会消耗内存;线程池的好处,就是可以方便的管理线程,也可以减少内存的消耗。

在springboot  提供ThreadPoolTaskExecutor 线程池

无返回值的任务使用public void execute(Runnable command) 方法提交:子线程可能在主线程结束之后结束

有返回值的任务使用public <T> Future<T> submit(Callable) 方法提交:因为提交任务后有个取数据的过程,在从Future取数据的过程中,Callable自带的阻塞机制,这个机制保证主线程一定在子线程结束之后结束。反之如果没有取数据,子线程可能会在主线程结束之后才结束。

 Future:可用来接受多线程结果值

    其中有5个方法:比较常用的是 get() 和isDone()

 get()方法可以当任务结束后返回一个结果,如果调用时,工作还没有结束,则会阻塞线程,直到任务执行完毕

 get(long timeout,TimeUnit unit)做多等待timeout的时间就会返回结果

 cancel(boolean mayInterruptIfRunning)方法可以用来停止一个任务,如果任务可以停止(通过mayInterruptIfRunning来进行判断),则可以返回true,如果任务已经完成或者已经停止,或者这个任务无法停止,则会返回false.

 isDone()方法判断当前方法是否完成

 isCancel()方法判断当前方法是否取消

2. 实现方法

(1)配置线程池


@Configuration
public class GlobalConfigA {

    @Bean("taskExecutor")
    public ThreadPoolTaskExecutor defaultThreadPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心线程数目
        executor.setCorePoolSize(16);
        //指定最大线程数
        executor.setMaxPoolSize(64);
        //队列中最大的数目
        executor.setQueueCapacity(16);
        //线程名称前缀
        executor.setThreadNamePrefix("defaultThreadPool_");
        //rejection-policy:当pool已经达到max size的时候,如何处理新任务
        //CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
        //对拒绝task的处理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //线程空闲后的最大存活时间
        executor.setKeepAliveSeconds(60);
        //加载
        executor.initialize();
        return executor;
    }
}

(2)实现异步,多线程(@Async)


@Component
public class AsyncTask {

    @Async("taskExecutor")
    public void tesTask(int i){
        System.out.println(Thread.currentThread().getName()+"-----"+i);
    }

    @Async("taskExecutor")
    public  CompletableFuture stringTask(String str){
      
        return  CompletableFuture.completedFuture(str);
    }
}

(2)实现方式2

 executor.submit

//通过注解引入配置
@Resource(name = "taskExecutor")
private ThreadPoolTaskExecutor executor;
                        //使用Future方式执行多任务
                        //生成一个集合
                        List<Future> futures = new ArrayList<>();

                        //获取后台全部有效运营人员的集合
                        List<AdminUserMsgResponse> adminUserDOList = adminManagerService.GetUserToSentMsg(null);

                        for (AdminUserMsgResponse response : adminUserDOList) {
                            //并发处理
                            if (response.getMobile() != null) {
                                Future<?> future = executor.submit(() -> {
                                    //发送短信
                                    mobileMessageFacade.sendCustomerMessage(response.getMobile(), msgConfigById.getContent());
                                });
                                futures.add(future);
                            }
                        }

                      //查询任务执行的结果
                       for (Future<?> future : futureList) {
                            while (true) {//CPU高速轮询:每个future都并发轮循,判断完成状态然后获取结果,这一行,是本实现方案的精髓所在。即有10个future在高速轮询,完成一个future的获取结果,就关闭一个轮询
                     if (future.isDone()&& !future.isCancelled()) {//获取future成功完成状态,如果想要限制每个任务的超时时间,取消本行的状态判断+future.get(1000*1, TimeUnit.MILLISECONDS)+catch超时异常使用即可。
                         Integer i = future.get();//获取结果
                        System.out.println("任务i="+i+"获取完成!"+new Date());
                        list.add(i);
                        break;//当前future获取结果完毕,跳出while
                    } else {
                        Thread.sleep(1);//每次轮询休息1毫秒(CPU纳秒级),避免CPU高速轮循耗空CPU---》新手别忘记这个
                    }
                }
             }

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值