Java开启异步的两种方式

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

1、注解开启:@Async

1.1、配置异步的线程池

  • 必须配置异步线程池,否则异步不会生效。
  • @EnableAsync 注解:指定异步线程池。不指定默认使用:SimpleAsyncTaskExecutor线程池
  • SimpleAsyncTaskExecutor是一个最简单的线程池,它没有任何的线程相关参数配置,它会为每个任务创建一个新的线程来执行,因此不建议在生产环境中使用。
  • 配置线程池见:http://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的多线程开发》
本文转载于网络 如有侵权请联系删除

相关文章

  • C# 常用接口学习 IEnumerable<T>

    我们先去看看公开的.Net4.0的源程序中IEnumerable<T>、IEnumerable、IEnumerator<T>和IEnumerator这四个接口是如何声明的:需加微信交流群的,请加小编微信号zls20210502,切记备注加群,小编将会第一时间邀请你进群!目前一群满员,只能进二群了!publicinterfaceIEnumerable<outT>:IEnumerable { newIEnumerator<T>GetEnumerator(); } publicinterfaceIEnumerator<outT>:IDisposable,IEnumerator { newTCurrent{ get; } } publicinterfaceIEnumerable { IEnumeratorGetEnumerator(); } publicinterfaceIEnumerator { boolMoveNext(); ObjectCurrent{ get; } voidReset(); }一、接口IEnumerab

  • 在 Linux 上使用密码加密和解密文件

    安装年龄Age可以从大多数Linux存储库安装。在Fedora上安装它:$ sudo dnf install age -y复制加密和解密文件随年龄增长Age可以使用公钥或用户设置的密码来加密和解密文件。使用带有公钥的年龄首先,生成一个公钥并将输出写入key.txt文件:$age-keygen -o key.txt Publickey:age16frc22wz6z206hslrjzuv2tsfgdfbvfdsbsdfbdfsasahrmxhudawase896m9复制使用公钥加密要使用您的公钥加密文件:$ touch mypasswds.txt | age -r ageage16frc22wz6z206hslrjzuv2tnsuw32rk80pnrku07fh7hrmxhudawase896m9 > mypass.tar.gz.age复制在这个例子中,文件mypasswds.txt是用我生成的公钥加密的,并放在一个名为mypass.tar.gz.age.用公钥解密要解密您保护的信息,请使用age命令和--decrypt选项:$ age --decrypt -i key.txt -o

  • 接口自动化读取excel中数据

    接口自动化是目前测试的一大主流,也是面试常见问题,一起来学习下吧!常见的自动化测试可以分为:数据驱动类别:一般通过excel中数据来测试;代码驱动:一般测试用例以代码为主,通过读取代码进行测试;关键字驱动:偏ui自动化,其中robotframework就是典型的关键字驱动框架;接口自动化用例设计:基本设计用例的方法和功能测试一致接口自动化步骤:获取测试用例+调用测试接口+结果校验+发送测试报告+异常处理接口测试网址:http://doc.nnzhp.cn/index.php?s=/6&page_id=12目录结构如下:备注:我这边就是先熟悉下怎么获取表格的数据,这是一个最简单的请求了,后期会对方法进行封装,以及一些错误日志打印、发送邮件等。代码信息看不清楚的可以去我的博客中查看,地址:https://blog.csdn.net/weixin_38961318运用的代码:requests.post(url,data,json,**kwargs)调用post请求,返回响应的相关信息requests.get(url,params=None,**kwargs)调用get请求,输入请求参

  • 6.scala元组

    在Scala中,元组是一个可以容纳不同类型元素的类。元组是不可变的。当我们需要从函数返回多个值时,元组会派上用场。元组可以创建如下:valingredient=("Sugar",25):Tuple2[String,Int]复制这将创建一个包含一个String元素和一个Int元素的元组。Scala中的元组包含一系列类:Tuple2,Tuple3等,直到Tuple22。因此,当我们创建一个包含n个元素(n位于2和22之间)的元组时,Scala基本上就是从上述的一组类中实例化一个相对应的类,使用组成元素的类型进行参数化。上例中,ingredient的类型为Tuple2[String,Int]。访问元素使用下划线语法来访问元组中的元素。‘tuple._n’取出了第n个元素(假设有足够多元素)。println(ingredient._1) println(ingredient._2)复制解构元组数据Scala元组也支持解构。val(name,quantity)=ingredient println(name) println(quantity)复制元组解构也可用于模式匹配。复

  • jmeter笔记(二):通过jython连接Oracle数据库

    (一)说明    本文说明在jmeter中如何通过jython连接Oracle数据库。    因为pythoncx_oracle库底层是用C实现的,在jython中用不了,这里用纯Java实现的zxJDBC。     zxJDBC符合 PythonDBAPI 规范。    zxJDBC已经整合到jython中,所以不需要另外安装。    说明文档:http://web.mit.edu/jython/jythonRelease_2_2alpha1/Doc/zxjdbc.html(二)通过zxJDBC连接Oracle数据  自己电脑没装Oracle数据库,就不截运行成功的图了,不过在公司内网是验证过没问题的。  这里要注意2点:     1、要设置默认编码格式,不然会报错     2、字典DADABASE中NAME指的是INSTANCE_NAME,数据库中用下面的SQL查询可以得到       SELECTINSTANCE_NAME FROMv$instance1importsys 2sys.path.append('C:\Users\laiqu\AppData\Local\Pr

  • 基于风险的应用程序安全方法可增强安全防御

    如今,不可否认的是网络犯罪已逐渐进入人们的生活,为人们所重视。无论何时,随意浏览新闻都能看到新漏洞的发现,或者是敏感信息的泄露、窃取等。因此,任何企业董事会都应该尽早加强网络安全防御。然而,即使现在网络威胁来势汹涌,但是网络安全防御仍然不够。通常而言,当最佳安全实践有可能干扰业务效率或整体生产力时,业务优先级往往是高于安全优先级的。对于许多CSO和CISO来说,资金不足是另一个值得普遍关注的问题,董事会根本没有准备好,没有为他们提供真正需要的预算和资源,来确保他们的业务安全。企业需要有长远考虑在短期内,减少安全资金以促进业务的其他领域发展似乎是个好主意,但这是一个很大的风险,一旦高管人员也受到攻击,后果更加不堪设想。例如,尽管在年度预算周期内,额外拨出50万英镑作为新的安全资源投入似乎并不可行,但与数据泄露后面临的数百万英镑的罚款、法律费用和缓解费用相比,这显得相形见绌。英国航空公司(BritishAirways)在其网站上称遭到“复杂的恶意犯罪袭击”之后,就被信息专员办公室(ICO)罚款1.83亿英镑,因为在此期间,约有50万名客户的详细信息泄露。这样的例子强调了通过实施网络安全实践

  • [译]写给初学者的Tensorflow介绍(2)

    去年我翻译了一篇文章:写给初学者的Tensorflow介绍,但这只是文章的第一部分,由于原作者迟迟没有写第二部分,我后来就把这件事情忘了。前几天,有朋友留言问为什么没有第二部分的内容,还有朋友热心的给出了第二部分的原文链接。所以在此把第二部分的内容也翻译出来,原文地址:https://medium.com/buzy-developers/a-beginner-introduction-to-tensorflow-part-2-6b4dc25ea51。点击阅读原文可以跳转到该文章,需要访问外国网站哦! 在上一部分中,我写了一些非常重要的关于使用Tensorflow构建机器学习模型的核心理论概念。 Tensorflow的核心组件是张量和计算图(或数据流图)。Tensorflow只是一个将运算表示为计算图的框架。然后Tensorflow将图划分为许多彼此独立的子图,这些子图并行执行,当然这是TensorFlow的主要特性之一,它为其可扩展性做出了很大贡献。Tensorflow还具有另一个重要特性,它提供了各种现成的计算工具,可用于解决各种问题。这些计算工具也是计算图,一旦将它们添加到程序中,

  • MySQL5.7之开启远程连接 原

      Centos7上,对MySQL5.7开启远程连接。1.修改/etc/my.cnf[mysqld] validate_password=off复制2.命令行进入mysqlusemysql; GRANTALLON*.*TOroot@'%'IDENTIFIEDBY'密码'WITHGRANTOPTION; flushprivileges;复制3.与防火墙有关firewall-cmd--zone=public--add-port=3306/tcp--permanent firewall-cmd--reload复制4.在Navicat中连接就可以了。(adsbygoogle=window.adsbygoogle||[]).push({});

  • Lync Server 2013 部署前端池支持NLB吗?

      部署Lyncserver2013前端池时遇到负载均衡的问题,没有HLB的硬件负载均衡设备,使用DNS负载轮询poolA记录建立多条指向不同的前端服务器地址,在没有HLB对方发布时,使用路由器映射端口443-4443只能指向一台前端服务器地址,问题就来了。  想到了使用windows自带的NLB,在Technet没有查到相关Lyncserver2013部署支持NLB的明确说法,在Technet论坛里有人这样问题,也得到了notsupported的回答。http://social.technet.microsoft.com/Forums/lync/en-US/d229891b-a97c-4209-be20-21993aad8ed9/network-load-balancing-nlb-in-lync-2013-enterprise?forum=ocsplanningdeployment  还有针对NLB和HLB对比文章中,列举了NLB的缺陷: WindowsNLB haslotsoflimitationsandproblemsandthesecanbeespeciallyimporta

  • 2017 全日食,你准备好了吗?

    █本文译自2017年8月8日的Wolfram博客文章:GetReadyfortheTotalSolarEclipseof2017?byJeffBryant2017年8月21日,西半球将迎来很多人可能一辈子都没有见过的天文奇观。全日食将横跨美国和附近海洋。虽然这种日食在世界各地并不罕见,但发生在你身边的机会相当小,而且经常是一生一次的事,除非你经常周游世界。南边的48个州郡可以驱车前往观看今年的日全食。从地球观察者的角度来看,日全食是月球移到太阳的前面的结果。月球的阴影相当小,只能在小区域与地球表面接触,如下图所示。我们可以利用Wolfram语言中的3D图形来逼真模拟可视化这个事件。首先,我们将要使用纹理,使地球看起来更逼真。把纹理应用于旋转的球面:用圆锥体来表示地球的阴影:月球可以由一个简单的球体表示,该球体偏离场景中心,而其轨道则是一条简单的虚线3D路径。两者都参数化,因为月球的轨道将及时进入。能够为这些函数提供值以使阴影出现在我们想要的地方是有用的。与地球的阴影一样,我们把月亮的阴影也表示为圆锥体。最后,我们创建其他场景元素用于标注。现在我们只需要组合场景。我们希望月亮能直接与太阳

  • Zookeeper的集群选举机制

    前言ZooKeeper服务器会在本地处理只读请求(exists、getData和getChildren)。假如一个服务器接收到客户端的getData请求,服务器读取该状态信息,并将这些信息返回给客户端。因为服务器会在本地处理请求,所以ZooKeeper在处理以只读请求为主要负载时,性能会很高。我们还可以增加更多的服务器到ZooKeeper集群中,这样就可以处理更多的读请求,大幅提高整体处理能力。那些会改变ZooKeeper状态的客户端请求(create、delete和setData)将会被转发给群首,集群在同一时刻只会存在一个群首,其他服务器追随群首被称为追随者(follower)。群首作为中心点处理所有对ZooKeeper系统变更的请求,它就像一个定序器,建立了所有对ZooKeeper状态的更新的顺序。Leader接收到客户端的请求后,会将请求构建成一个提议(Proposal),同时会为该提议绑定一个zxid(zxid可以表示执行顺序),然后将该提议广播到集群上的所有服务器,Leader等待Follwer反馈,当有过半数(>=N/2+1)的Follower反馈信息后,Leade

  • SpringBoot+Mybatis以及jsp使用问题

    SpringBoot实现Mybatis的整合 复制a.POM中引入依赖<!--SpringJDBC依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!--MySql驱动依赖--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--MyBatis依赖--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>myba

  • MS leetcode 题目

    #717 1比特与2比特字符:判断末尾符号是哪一种 思路:线性从前向后遍历,维护一个映射list。 classSolution: defisOneBitCharacter(self,bits:List[int])->bool: iflen(bits)==1: returnTrue else: mapList=[] whilelen(bits)>0: ifbits[0]==1: mapList.append('F') bits.pop(0) bits.pop(0) else: mapList.append('T') bits.pop(0) ifmapList[-1]=='T': returnTrue else: returnFalse复制 ViewCode #67 二进制求和:二进制加法 思路:首先处理字符串长度不一致的问题,为较短的字符串前面添0,将两个字符串补齐。然后从后往前加即可,当前位置上的两个数+进位。 classSolution: defaddZero(self,a,b): diff=abs(len(b)-len(a)) iflen

  • im2rec 修改resize

    https://github.com/apache/incubator-mxnet/blob/master/tools/im2rec.py#L196 源码是按照比例修改resize。 现在需要改一个自己的定制大小;  

  • jquery点击输入框提示文字消失输入文字变色

      <inputname=""type="text"value="请填写学校全称"class="txt"> <inputname=""type="text"value="规范,如:一(1)班"class="txt"> <inputname=""type="text"class="txt"value="请填写真实姓名"> <inputname=""type="text"class="txt"value="请填写联系方式"> <inputname=""type="text"class="txt"value="规范,如:《我的我的祖国》">复制 <script> $(function(){ $('.txt').bind({ focus:function(){ if(this.value==this.defaultValue){ this.value=""; this.style.color='#000' } }, blur:function(){ if(this.value==""){ this.valu

  • 1.新建画布

    点击文件(F)--新建(N) 1.像素--分辨率 右边选择宽度和高度,可以选择像素或者我们熟悉的厘米。 若新建的海报是在电脑显示屏上显示则选择默认电脑分辨率的像素。宽度X高度1920X1080像素 分辨率--单位PPI(像素/英寸) 分辨率表示单位长度内像素点的数量。决定图像的精细程度,分辨率越高,图像越精细。 如果图像是在显示器(手机,电脑)或者多媒体设备显示时,分辨率设置为:72PPI。 印刷的海报使用国际通用分辨率:300PPI 海报高清写真96-200PPI 大型喷绘25-50PPI 2.颜色模式 RGB&CMYK RGB是工业界的一种颜色标准,是通过对红(R)绿(G)蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色。(针对电子产品的显示) CMYK是针对印刷设定的颜色标准,是通过对青(C)、洋红(M)、黄(Y)、黑(K)四种颜色变化以及它们之间的叠加来得到各式各样的颜色。 CMYK代表(C)、洋红(M)、黄(Y)、黑(K)四种印刷专用的油墨颜色;在CMYK模式下Photoshop通道中即为这四种颜色。 设置好之后点击创建。   &nb

  • React interrelated reference Manual

    React本教程描述一些基本概念 如果需要入门学习,推荐教程:https://reactjs.org/ 本教程为了加强记忆,更改了学习的顺序。且会收集教程以外实例。 0.知识 1.React组件API&&React组件 2.React元素渲染 3.ReactJSX 4.This&&事件处理HandlingEvents 5.React条件渲染&&React列表&Keys 6.Hook&&ReactState(状态) 7.常用 React实现了与浏览器无关的DOM系统,以实现性能和跨浏览器的兼容性。 0.知识 0.1,ES6箭头函数: graphLR A[箭头函数]--没有将自己绑定到-->B((关键词)) B-->C(arguments) B-->D{super} B-->E{new.target} B-->F{this} 箭头函数表达式的语法比函数表达式更简洁,并且没有自己的this,arguments,super或new.target。箭头函数表达式更适用于那些本来需要匿名

  • 标准输出设备

    向文本文件输出 标准输出设备显示器被系统看作文本文件,所以我们以向标准设备输出为例,介绍文本文件输出格式控制。 插入运算符 插入(<<)运算符 为所有标准C++数据类型预先设计的,用于传送字节到一个输出流对象。 操纵符(manipulator) 插入运算符与操纵符一起工作 控制输出格式。 很多操纵符都定义在 ios_base类中(如hex())、头文件(如setprecision())。 控制输出宽度 在流中放入setw操纵符或调用width成员函数为每个项指定输出宽度。 setw和width仅影响紧随其后的输出项,但其它流格式操纵符保持有效直到发生改变。 dec、oct和hex操纵符设置输入和输出的默认进制。 setiosflags操纵符 这个程序中,通过使用带参数的setiosflags操纵符来设置左对齐,setiosflags定义在头文件iomanip中。 参数iosbase::left是iosbase的静态常量,因此引用时必须包括ios_base::前缀。 这里需要用resetiosflags操纵符关闭左对齐标志。setiosfla

  • 献芹奏曝-Python面试题-算法-动态规划篇

       上一篇:献芹奏曝-Python面试题     开篇的话:本文目的是收集和归纳力扣上的算法题,希望用python语言,竭我所能做到思路最清奇、代码最简洁、方法最广泛、性能最高效,了解常见题目,找到最利于记忆的答案,更加从容的应对面试。希望广思集益,共同进步。  动态规划篇  70. 爬楼梯(难度系数✯) classSolution: defclimbStairs(self,n:int)->int: ifn==1: return1 elifn==2: return2 else: returnself.climbStairs(n-1)+self.climbStairs(n-2)复制 方法一 运行结果:1:超时 知识点/技巧:递归调用,会有大量重复计算 classSolution: dict_result={} defclimbStairs(self,n:int)->int: ifself.dict_result.get(n): returnself.dict_

  • CSS预处理器(less 和 sass)

    CSS预处理器 1.基于CSS的另一种语言 2.通过工具编译成CSS 3.添加了很多CSS不具备的特性 4.能提升CSS文件的组织 提供功能:1.嵌套反映层级和约束2.变量和计算,减少重复戴拿3.Extend和Mixin代码片段 4.循环适用于复杂有规律的样式5.importCSS文件模块化 知识点: 1.less(嵌套) body{ padding:0; margin:0; } .wrapper{ background:white; .nav{ font-size:12px; } .content{ font-size:14px; &:hover{ background:red; } } } 复制 2.sass嵌套 body{ padding:0; margin:0; } .wrapper{ background:white; } .wrapper.nav{ font-size:12px; } .wrapper.content{ font-size:14px; } .wrapper.content:hover{ background:red; } 复制 3

  • 正则积累

    *重复零次或更多次(>=0次) + 重复一次或更多次(>=1次) ? 重复零次或一次(0次或者1次) {n} 重复n次 {n,}重复n次或更多次 {n,m}重复n到m次   .匹配除换行符以外的任意字符 \w 匹配字母或数字或下划线或汉字 \s 匹配任意的空白符 \d 匹配数字 \b 匹配单词的开始或结束 ^ 匹配字符串的开始 $ 匹配字符串的结束   \W匹配任意不是字母,数字,下划线,汉字的字符 \S 匹配任意不是空白符的字符 \D 匹配任意非数字的字符 \B 匹配不是单词开头或结束的位置 [^x] 匹配除了x以外的任意字符 [^aeiou] 匹配除了aeiou这几个字母以外的任意字符 开心的做一个无忧无虑的码农,争取每天进步一点。

相关推荐

推荐阅读