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结果";
    //            }
    //        };
        }

    路在脚下
  • 相关阅读:
    WebView与 JS 交互方式
    ES6常用知识点
    Flash Builder 破解与开发环境配置
    如何修改默认浏览器
    基本数据类型和常用内建对象
    VS 2010 使用技巧
    javascript之事件驱动编程的几个基本概念
    javascript笔记之DHTML基础
    浏览器对象模型
    开发心得记录
  • 原文地址:https://www.cnblogs.com/lgg20/p/15472392.html
Copyright © 2011-2022 走看看