Springboot 多线程执行

springboot 多线程执行

一.springboot开线程执行异步任务

1.Spring通过任务执行器TaskExecutor,来实现多线程和并发编程,使用ThreadPoolTaskExecutor可实现一个基于线程池的TaskExecutor;

2.异步需要在配置类上面加@EnableAsync 来开启对异步任务的支持在需要异步执行的方法上面加@Async 来声明这个方法是一个需要异步执行的方法;

3.让配置类实现AsyncConfigurer接口,并重写getAsyncExecutor方法,并返回一个ThreasPoolTaskExecutor,就可以获取一个基于线程池的TaskExecutor;

4.@Async 用在方法上,表示这个方法是一个异步的方法,如果用在类上面,表明这个类中的所有方法都是异步的方法。

(1).配置类

package com.ifly.jkoala.modules.contract.config;

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

/**

  • ThreadConfig

  • Description:

  • Spring通过任务执行器TaskExecutor,

  • 来实现多线程和并发编程,

  • 使用ThreadPoolTaskExecutor可实现一个基于线程池的TaskExecutor;

  • @author tuzi

  • @date 2021/7/12 13:55
    /
    @Configuration
    @EnableAsync
    @ComponentScan(“com.ifly.jkoala.modules.contract.service”)
    public class ThreadConfig implements AsyncConfigurer {
    /
    *

    • ThredPoolTaskExcutor的处理流程
    • 当池子大小小于corePoolSize,就新建线程,并处理请求
    • 当池子大小等于corePoolSize,把请求放入workQueue中,池子里的空闲线程就去workQueue中取任务并处理
    • 当workQueue放不下任务时,就新建线程入池,并处理请求,如果池子大小撑到了maximumPoolSize,就用RejectedExecutionHandler来做拒绝处理
    • 当池子的线程数大于corePoolSize时,多余的线程会等待keepAliveTime长时间,如果无请求可处理就自行销毁
    • @return
      */
      @Override
      public Executor getAsyncExecutor() {
      ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
      executor.setCorePoolSize(5);
      executor.setMaxPoolSize(15);
      executor.setQueueCapacity(25);
      executor.initialize();
      return executor;
      }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    return null;
    }
    }

(2).异步任务

package com.ifly.jkoala.modules.contract.service;

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import java.util.concurrent.Future;

/**

  • TaskService

  • Description:

  • @author tuzi

  • @date 2021/7/12 15:58
    */
    @Service
    public class TaskService {

    /**

    • 表明是异步调用
    • 没有返回值
      */
      @Async
      public void excutVoidTask(int i) {
      System.out.println(“异步执行任务第[” + i + “] 个”);
      }

    @Async
    public Future excuteValueTask(int i) throws InterruptedException {
    Thread.sleep(1000);
    Future future = new AsyncResult("success is " + i);
    System.out.println(“异步执行任务第[” + i + “] 个”);
    return future;
    }
    }

(3).测试异步任务

package com.ifly.jkoala;

import com.ifly.jkoala.modules.contract.service.TaskService;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.task.TaskRejectedException;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**

  • ThreadTest

  • Description:

  • @author tuzi

  • @date 2021/7/12 16:23
    */
    @RunWith(SpringRunner.class)
    @Slf4j
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    public class ThreadTest {

    @Autowired
    private TaskService service;

    /**

    • 没有返回值测试
      */
      @Test
      public void testVoid() {
      for (int i = 0; i < 20; i++) {
      service.excutVoidTask(i);
      }
      System.out.println(“主线程执行完毕=”);
      }

    @Test
    public void testReturn() throws InterruptedException, ExecutionException {
    List<Future> lstFuture = new ArrayList<>();// 存放所有的线程,用于获取结果
    for (int i = 0; i < 100; i++) {
    while (true) {
    try {
    // 线程池超过最大线程数时,会抛出TaskRejectedException,则等待1s,直到不抛出异常为止
    Future stringFuture = service.excuteValueTask(i);
    lstFuture.add(stringFuture);
    break;
    } catch (TaskRejectedException e) {
    System.out.println(“线程池满,等待1S。”);
    Thread.sleep(1000);
    }
    }
    }

     // 获取值.get是阻塞式,等待当前线程完成才返回值
     for (Future<String> future : lstFuture) {
         System.out.println(future.get());
     }
     System.out.println("========主线程执行完毕=========");
    

    }

}

testVoid 方法执行结果:
在这里插入图片描述
testReturn 方法返回结果:
线程池满,等待1S。
线程池满,等待1S。
异步执行任务第[33] 个
异步执行任务第[1] 个
异步执行任务第[0] 个
异步执行任务第[32] 个
异步执行任务第[31] 个
异步执行任务第[30] 个
异步执行任务第[4] 个
异步执行任务第[3] 个
异步执行任务第[2] 个
异步执行任务第[39] 个
异步执行任务第[37] 个
异步执行任务第[38] 个
异步执行任务第[36] 个
异步执行任务第[35] 个
异步执行任务第[34] 个
线程池满,等待1S。
异步执行任务第[5] 个
异步执行任务第[7] 个
异步执行任务第[9] 个
异步执行任务第[8] 个
异步执行任务第[6] 个
异步执行任务第[10] 个
异步执行任务第[11] 个
异步执行任务第[12] 个
异步执行任务第[13] 个
异步执行任务第[14] 个
异步执行任务第[15] 个
异步执行任务第[16] 个
异步执行任务第[17] 个
异步执行任务第[18] 个
异步执行任务第[19] 个
线程池满,等待1S。
异步执行任务第[20] 个
异步执行任务第[22] 个
异步执行任务第[21] 个
异步执行任务第[23] 个
异步执行任务第[24] 个
异步执行任务第[25] 个
异步执行任务第[26] 个
异步执行任务第[27] 个
异步执行任务第[28] 个
异步执行任务第[40] 个
异步执行任务第[29] 个
异步执行任务第[41] 个
异步执行任务第[42] 个
异步执行任务第[44] 个
异步执行任务第[43] 个
线程池满,等待1S。
异步执行任务第[45] 个
异步执行任务第[47] 个
异步执行任务第[50] 个
异步执行任务第[51] 个
异步执行任务第[49] 个
异步执行任务第[48] 个
异步执行任务第[46] 个
异步执行任务第[52] 个
异步执行任务第[54] 个
异步执行任务第[56] 个
异步执行任务第[55] 个
异步执行任务第[53] 个
异步执行任务第[57] 个
异步执行任务第[58] 个
异步执行任务第[59] 个
success is 0
success is 1
success is 2
success is 3
success is 4
success is 5
success is 6
success is 7
success is 8
success is 9
success is 10
success is 11
success is 12
success is 13
success is 14
success is 15
success is 16
success is 17
success is 18
success is 19
success is 20
success is 21
success is 22
success is 23
success is 24
success is 25
success is 26
success is 27
success is 28
success is 29
success is 30
success is 31
success is 32
success is 33
success is 34
success is 35
success is 36
success is 37
success is 38
success is 39
success is 40
success is 41
success is 42
success is 43
success is 44
success is 45
success is 46
success is 47
success is 48
success is 49
success is 50
success is 51
success is 52
success is 53
success is 54
success is 55
success is 56
success is 57
success is 58
success is 59
异步执行任务第[60] 个
success is 60
异步执行任务第[65] 个
异步执行任务第[61] 个
异步执行任务第[64] 个
异步执行任务第[62] 个
异步执行任务第[63] 个
异步执行任务第[67] 个
异步执行任务第[66] 个
success is 61
success is 62
success is 63
success is 64
success is 65
success is 66
success is 67
异步执行任务第[71] 个
异步执行任务第[70] 个
异步执行任务第[69] 个
异步执行任务第[68] 个
success is 68
success is 69
success is 70
success is 71
异步执行任务第[74] 个
异步执行任务第[73] 个
异步执行任务第[72] 个
success is 72
success is 73
success is 74
异步执行任务第[75] 个
success is 75
异步执行任务第[78] 个
异步执行任务第[82] 个
异步执行任务第[81] 个
异步执行任务第[80] 个
异步执行任务第[79] 个
异步执行任务第[77] 个
异步执行任务第[76] 个
success is 76
success is 77
success is 78
success is 79
success is 80
success is 81
success is 82
异步执行任务第[83] 个
success is 83
异步执行任务第[85] 个
异步执行任务第[84] 个
success is 84
success is 85
异步执行任务第[86] 个
success is 86
异步执行任务第[89] 个
异步执行任务第[87] 个
success is 87
异步执行任务第[88] 个
success is 88
success is 89
异步执行任务第[90] 个
success is 90
异步执行任务第[94] 个
异步执行任务第[97] 个
异步执行任务第[95] 个
异步执行任务第[96] 个
异步执行任务第[93] 个
异步执行任务第[91] 个
异步执行任务第[92] 个
success is 91
success is 92
success is 93
success is 94
success is 95
success is 96
success is 97
异步执行任务第[98] 个
异步执行任务第[99] 个
success is 98
success is 99
主线程执行完毕=

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值