zoukankan      html  css  js  c++  java
  • springboot多线程使用方式

    一、简单介绍

    2.1. TaskExecutor---Spring异步线程池的接口类,其实质是java.util.concurrent.Executor

    以下是官方已经实现的全部7个TaskExecuter。Spring宣称对于任何场景,这些TaskExecuter完全够用了:

    名字特点
    SimpleAsyncTaskExecutor 每次请求新开线程,没有最大线程数设置.不是真的线程池,这个类不重用线程,每次调用都会创建一个新的线程。 --【1】
    SyncTaskExecutor 不是异步的线程.同步可以用SyncTaskExecutor,但这个可以说不算一个线程池,因为还在原线程执行。这个类没有实现异步调用,只是一个同步操作。
    ConcurrentTaskExecutor Executor的适配类,不推荐使用。如果ThreadPoolTaskExecutor不满足要求时,才用考虑使用这个类。
    SimpleThreadPoolTaskExecutor 监听Spring’s lifecycle callbacks,并且可以和Quartz的Component兼容.是Quartz的SimpleThreadPool的类。线程池同时被quartz和非quartz使用,才需要使用此类。
    ThreadPoolTaskExecutor 最常用。要求jdk版本大于等于5。可以在程序而不是xml里修改线程池的配置.其实质是对java.util.concurrent.ThreadPoolExecutor的包装。

    方式1:Executors new一个CachedThreadPool线程池。

    private static final ExecutorService executorService = Executors.newCachedThreadPool(new BasicThreadFactory.Builder()
                .namingPattern("create-card-thread-%d")
                .build());
    
    CompletableFuture.runAsync(createCards(reqVO, buId), executorService)
            .whenComplete((Void v, Throwable t) -> {
                if (t == null) {
                    log.info("create card complete.batchId={}", reqVO.getBatchId());
                } else {
                    log.error("create card failed.batchId={}", reqVO.getBatchId(), t);
                }
                try (ShardingCtx s = ShardingCtx.setShardingValue(buId)) {
                    CustomerIntGencardLogPO updateLog = new CustomerIntGencardLogPO();
                    updateLog.setPk(gencardLogPO.getPk())
                            .setLastUpdated(LocalDateUtil.localDateTimeMinus8Hours(LocalDateTime.now()))
                            .setGencardStatus(PROCESSED);
                    customerIntGencardLogMapper.updateById(updateLog);
                }
            });

    方式二:注入:@Autowire   @Resource

    @Service
    public class AsyncService {

    @Autowired //1.注入默认的线程池
    @Resource("taskExecutor") //2.自定义的线程池
    ThreadPoolTaskExecutor threadPoolTaskExecutor;

    public void addEventLog(String buId, String status){
    CustomerEventLogPO customerEventLog = new CustomerEventLogPO();
    customerEventLog.setUuid(uuid);
    customerEventLog.setStatus(status);
    customerEventLog.setCreated(LocalDateTime.now());
    customerEventLogMapper.insert(customerEventLog);

    threadPoolTaskExecutor.submit(new Thread(()->{
    customerEventLogMapper.insert(customerEventLog);
    })); //submit有返回值

    threadPoolTaskExecutor.execute(new Thread(()->{
    customerEventLogMapper.insert(customerEventLog);
    })); //execute无返回值

      taskExecutor.execute(new Runnable() { 
            @Override 
            public void run() { 
              // TODO 
              try { 
                  studentscount = coursesService.getStudentCount(pd); 
              } catch (Exception e) { 
                // TODO Auto-generated catch block 
                e.printStackTrace(); 
              } 
            } 
          }); 
        }

    }

    方式三: 方法上直接加注解: @Async("taskExecutor")  taskExecutor是自定义的bean或者默认的。

        @Async("taskExecutor")
        @DynamicDatasource
        public void addEventLog(String buId, String uuid, String evenType, String eventData, Exception e, String status){
            CustomerEventLogPO customerEventLog = new CustomerEventLogPO();
            customerEventLog.setUuid(uuid);
            customerEventLog.setEventType(evenType);
            customerEventLog.setEventData(eventData);
            customerEventLog.setStatus(status);
            customerEventLog.setDescripe(e != null ? e.getMessage() : "");
            customerEventLog.setCreated(LocalDateTime.now());
            customerEventLogMapper.insert(customerEventLog);
        }

    方式四:结论:在main方法里面的用线程池开多线程,不是按main方法执行顺序完再执行多线程,而是运行到新线程的地方,如果新线程先跑,那就在main方法之前

    public static void main(String[] args) {
    
            System.out.println("开始main线程..."+ Thread.currentThread().getName());
            //jav8写法:
            Runnable runnable = () -> System.out.println("执行runnable任务1..."+ Thread.currentThread().getName());
    
            //jav8写法:泛型代表了任务执行的返回类型
            Callable<String> callable = () -> {
                System.out.println("执行callable计算任务..." + Thread.currentThread().getName());
                return "返回callable任务结果";
            };
            ExecutorService service = Executors.newFixedThreadPool(2);
    
            //Runnable任务使用execute方法
            service.execute(runnable);
            System.out.println("开始main线程2..."+ Thread.currentThread().getName());
            //Callable任务使用submit方法。这个方法是异步的。。
            Future future = service.submit(callable);
    
            System.out.println("结束main线程..."+ Thread.currentThread().getName());
            try {
                System.out.println(future.get());
            } catch (InterruptedException | ExecutionException e) {
            }
    
    //        //老的写法:
    //        Runnable runnable2 = new Runnable() {
    //            @Override
    //            public void run() {
    //                System.out.println("执行任务1...");
    //            }
    //        };
    
    //        //老的写法: 泛型代表了任务执行的返回类型
    //        Callable<String> callable = new Callable<String>() {
    //            @Override
    //            public String call() throws Exception {
    //                System.out.println("执行计算任务2...");
    //                return "任务2结果";
    //            }
    //        };
        }

    路在脚下
  • 相关阅读:
    Maven 集成Tomcat插件
    dubbo 序列化 问题 属性值 丢失 ArrayList 解决
    docker 中安装 FastDFS 总结
    docker 从容器中拷文件到宿主机器中
    db2 相关命令
    Webphere WAS 启动
    CKEDITOR 4.6.X 版本 插件 弹出对话框 Dialog中 表格 Table 自定义样式Style 问题
    SpringMVC JSONP JSON支持
    CKEDITOR 3.4.2中 按钮事件中 动态改变图标和title 获取按钮
    git回退到远程某个版本
  • 原文地址:https://www.cnblogs.com/lgg20/p/15472392.html
Copyright © 2011-2022 走看看