最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

Java开启异步的两种方式

来源:博客园


(相关资料图)

二、Java开启异步的两种方式

1、注解开启:@Async

1.1、配置异步的线程池

  • 必须配置异步线程池,否则异步不会生效。
  • @EnableAsync 注解:指定异步线程池。不指定默认使用:SimpleAsyncTaskExecutor线程池
  • SimpleAsyncTaskExecutor是一个最简单的线程池,它没有任何的线程相关参数配置,它会为每个任务创建一个新的线程来执行,因此不建议在生产环境中使用。
  • 配置线程池见:https://www.cnblogs.com/kakarotto-chen/p/17428432.html
package com.cc.md.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.scheduling.annotation.EnableAsync;import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.ThreadPoolExecutor;/** IO型的线程池 * @author CC * @since 2023/5/23 0023 */@Configuration@EnableAsyncpublic class IoThreadPool {    public static final int THREAD_SIZE = 2 * (Runtime.getRuntime().availableProcessors());        public static final int QUEUE_SIZE = 1000;    @Bean(name = "myIoThreadPool")    public ThreadPoolTaskExecutor threadPoolExecutor(){        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();        executor.setCorePoolSize(THREAD_SIZE);        executor.setMaxPoolSize(THREAD_SIZE);        executor.setQueueCapacity(QUEUE_SIZE);        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());        executor.setKeepAliveSeconds(60);        executor.setAllowCoreThreadTimeOut(true);        executor.setAwaitTerminationSeconds(300);        executor.setWaitForTasksToCompleteOnShutdown(true);        executor.setThreadNamePrefix("myIo-Th-Pool-");        executor.initialize();        return executor;    }}

1.2、异步方法

  • 异步方法必须写在另一个类中,否则不生效
  • @Async可以打在类上、也可以打在方法上
1 @Async:类上,说明整个类中的方法都是异步。必须写我们自己配置的线程池 —— ("myIoThreadPool")    2 @Async:方法上,说明这个方法是异步。不用写我们自己配置的线程池
  • 异步接口+实现类

接口

package com.cc.md.service;/** * @author CC * @since 2023/5/24 0024 */public interface IAsyncService {    /** 异步方法1     * @since 2023/5/24 0024     * @author CC     **/    void async1();    /** 异步方法2     * @since 2023/5/24 0024     * @author CC     **/    void async2();}

实现类

package com.cc.md.service.impl;import com.cc.md.service.IAsyncService;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.scheduling.annotation.Async;import org.springframework.stereotype.Service;/** 1 @Async:类上,说明整个类中的方法都是异步。必须写我们自己配置的线程池 —— ("myIoThreadPool") *  2 @Async:方法上,说明这个方法是异步。不用写我们自己配置的线程池 * @author CC * @since 2023/5/24 0024 */@Service@Async("myIoThreadPool")public class AsyncServiceImpl implements IAsyncService {    private static final Logger log = LoggerFactory.getLogger(AsyncServiceImpl.class);    //类上写了@Async,这里就可以不写了。    //可以不写 ("myIoThreadPool")。因为在IoThreadPool中开启了异步,说明异步用的就是我们配置的io线程池    //如果类上面打了 @Async ,这里必须写:("myIoThreadPool")    @Override    //@Async    public void async1(){        //模仿io流耗时        try {            Thread.sleep(5000);        } catch (InterruptedException e) {            throw new RuntimeException(e);        }        log.info("打印:{}", "异步方法1111!");    }    //@Async在类上面,说明这个方法也是异步方法。如果不打,无法开启异步。    @Override    public void async2(){        //模仿io流耗时        try {            Thread.sleep(5000);        } catch (InterruptedException e) {            throw new RuntimeException(e);        }        log.info("打印:{}", "异步方法2222!");    }}

1.3、测试

@Resource    private IAsyncService asyncService;        //开启异步1 —— @Async    @Test    public void test03() throws Exception {        log.info("打印:{}", "异步测试的-主方法1");        asyncService.async1();        asyncService.async2();        //不会等待异步方法执行,直接返回前端数据        log.info("打印:{}", "异步测试的-主方法2");    }

结果:

2、CompletableFuture的方式

使用:

@Resource(name = "myIoThreadPool")    private ThreadPoolTaskExecutor myIoThreadPool;        //开启异步2 —— CompletableFuture.runAsync()    @Test    public void test04() throws Exception {        log.info("打印:{}", "异步测试的-主方法1");        CompletableFuture.runAsync(() -> {            log.info("打印:{}", "异步方法1!");            //异步执行的代码,也可以是方法,该方法不用单独写到其他类中。            this.async2("异步方法1!-end");        }, myIoThreadPool);        //不会等待异步方法执行,直接返回前端数据        log.info("打印:{}", "异步测试的-主方法2");    }    //异步需要执行的方法,可以写在同一个类中。    private void async2(String msg) {        //模仿io流耗时        try {            Thread.sleep(5000);        } catch (InterruptedException e) {            throw new RuntimeException(e);        }        log.info("打印:{}", msg);    }

结果:

  • 后续CompletableFuture的使用见:《Java的CompletableFuture,Java的多线程开发》

关键词: