首页 > 编程语言 >Java开启异步的两种方式

Java开启异步的两种方式

时间:2023-05-24 16:13:11浏览次数:47  
标签:异步 Java import 开启 线程 executor Async 方法

二、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
@EnableAsync
public 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");
    }

结果:

image

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);
    }

结果:

image

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

标签:异步,Java,import,开启,线程,executor,Async,方法
From: https://www.cnblogs.com/kakarotto-chen/p/17428619.html

相关文章

  • 用命令行工具运行java文件
     1、若java文件有packagepackagequitStu;publicclassMain{publicstaticvoidmain(String[]args){for(Stringstr:args){if(str.equals("11")){System.out.println("-v1.0");brea......
  • Java如何生成随机数?要不要了解一下!
    前言我们在学习Java基础时就知道可以生成随机数,可以为我们枯燥的学习增加那么一丢丢的乐趣。本文就来介绍Java随机数。一、Random类介绍在Java中使用Random工具类来生成随机数,该类在java.util包下,在JDK1.0版本就存在了。Random单词本身就是随机、随意、任意的意思......
  • Java配置线程池
    一、Java配置线程池1、线程池分类、其他1.1、分类IO密集型和CPU密集型任务的特点不同,因此针对不同类型的任务,选择不同类型的线程池可以获得更好的性能表现。1.1.IO密集型任务​ IO密集型任务的特点是需要频繁读写磁盘、网络或者其他IO资源,执行时间长,CPU占用率较低。对......
  • 流程表单JavaScript代码
    ----订单流程-----------//表单加载初始化时functionpreinit(){}//表单加载完成,isrun代表流程是否流转中1-是,0-否functionLoaded(isrun){$("#om_order_status").attr("disabled","disabled");......
  • java入门2..0
    java的运行原理1.在本地磁盘中创建一个文本文件为Demo.java的源文件2.在源文件中编写java代码如下:publicclassDemopublicstaticvoid,main(String[]args){System.out.println(" ");}3.在当前文件目录下。输入cmd跳转到dos窗口4.通过java编译源文件。会生成字节码文件......
  • 剑指 Offer II 018(Java). 有效的回文(简单)
    题目:给定一个字符串s,验证s 是否是 回文串 ,只考虑字母和数字字符,可以忽略字母的大小写。本题中,将空字符串定义为有效的 回文串 。 示例1:输入:s="Aman,aplan,acanal:Panama"输出:true解释:"amanaplanacanalpanama"是回文串示例2:输入:s="raceacar"......
  • 【JavaWeb-02】Web服务器
    文章目录2.web服务器2.1技术讲解2.2web服务器2.web服务器2.1技术讲解JSP/Servlet:B/S:浏览和服务器C/S:客户端和服务端sun公司主推的B/S架构基于Java语言的(所有的大公司,或者一些开源的组件,都是用Java写的)可以承载三高问题带来的影响2.2web服务器IIS:微软的Tmocat:Java初学人员......
  • 京东数科java一面【过】
    自我介绍实习经历【聊了挺多】集合方面Collection【list(写时复制)/set/Queue(阻塞队列)】Map【HashTable/HashMap/ConcorrentHashMap】synchronized对象头原理的过程A系统1WTBS,B系统300TBS,问解决方法技术角度:读写分离、Kong层、加服务器业务角度:加锁、加进度条AQS是什么原理Volat......
  • 阿里蚂蚁集团Java一面【凉】
    一个小哥哥打来的电话1.自我介绍2.介绍实习实习的时候用到了分布式锁深挖分布式锁的实现【回去复盘】遇到了什么问题?为什么用这个?怎么用的?怎么实现?3.多服务器之间是怎么保持数据一致的【回去复盘】4.分布式事务5.微服务了解嘛【回去复盘】6.MySQL的索引7.MySQL的乐观锁......
  • 【从Java转C#】第三章:对象和类型
    目录对象和类型ref和out参数的使用方法的重载属性构造函数匿名类型结构【Struct】弱引用(WeakReference)静态类Object对象和类型ref和out双方都可以改变原始的地址初始值的不同ref:需要赋予变量初始值out:不需要赋予变量初始值namespaceConsoleApp1{classProgram{......