异步编程-线程实现异步编程

  • 使用线程实现异步
  • 第一种方式
  • 第二种方式
  • 问题

在日常开发中我们经常会遇到这样的情况,即需要异步地处理一些事情,而不需要知道异步任务的结果。比如在调用线程里面异步打日志,为了不让日志打印阻塞调用线程,会把日志设置为异步方式。

在Java中,每当我们需要执行异步任务时,可以直接开启一个线程来实现,也可以把异步任务封装为任务对象投递到线程池中来执行。接下来我们来看看Java如何实现异步。

使用线程实现异步

在Java中实现异步编程最简单的方式是:每当有异步任务要执行时,使用Tread类来创建一个线程来进行异步执行。在讲解如何显式使用Thread实现异步编程前,我们先来看下在同步编程模型下,在一个线程中要做两件事情的代码是怎样的

// 1.执行任务A
public static void doSomethingA() {try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("--- doSomethingA---");
}
// 2.执行任务B
public static void doSomethingB() {try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("--- doSomethingB---");
}public static void main(String[] args) {long start = System.currentTimeMillis();// 1.执行任务A doSomethingA();// 2.执行任务B doSomethingB();System.out.println(System.currentTimeMillis() - start);
}

运行上面代码会启动一个Java虚拟机进程,进程内会创建一个用户线程来执行main函数(main线程), main线程内首先执行了doSomethingA方法,然后执行了doSomethingB方法,那么整个过程耗时4s左右,因为这两个方法是按照顺序执行的。

在Java中,Java虚拟机允许应用程序同时运行多个执行线程,所以我们可在main函数内开启一个线程来异步执行任务doSomethingA,而main函数所在线程执行doSomethingB,即可大大缩短整个任务处理耗时。

第一种方式

Java中有两种方式来显式开启一个线程进行异步处理。实现java.lang.Runnable接口的run方法,然后传递Runnable接口的实现类作为创建Thread时的参数,启动线程,对应这种方式的main函数代码可以修改为如下所示:

public static void doSomethingA() {try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("--- doSomethingA---");
}public static void doSomethingB() {try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("--- doSomethingB---");
}public static void main(String[] args) throws InterruptedException {// 1.开启异步单元执行任务Along start = System.currentTimeMillis();Thread thread = new Thread(() -> {try {doSomethingA();} catch (Exception e) {e.printStackTrace();}}, "threadA");thread.start();// 2.执行任务BdoSomethingB();// 3.同步等待线程A运行结束thread.join();System.out.println(System.currentTimeMillis() - start);
}

如上面代码1,我们在main函数所在线程内首先使用lambda表达式创建了一个java.lang.Runnable接口的匿名实现类,用来异步执行doSomethingA任务,然后将其作为Thread的参数并启动。这时候线程A与main线程并发运行,也就是任务doSomethingA与任务doSomethingB并发运行,代码3则等main线程运行完doSomethingB任务后同步等待线程A运行完毕。运行上面代码,这时整个过程耗时大概2s,可知使用异步编程可以大大缩短任务运行时间。

第二种方式

Java中第二种开启线程进行异步执行的方式是实现Thread类,并重写run方法,这种方式的代码如下:

public static void main(String[] args) throws InterruptedException {long start = System.currentTimeMillis();// 1.开启异步单元执行任务A            Thread thread = new Thread("threadA") {@Overridepublic void run() {try {doSomethingA();} catch (Exception e) {e.printStackTrace();}}};thread.start();// 2.执行任务B                doSomethingB();// 3.同步等待线程A运行结束                thread.join();System.out.println(System.currentTimeMillis() - start);
}

上面代码1创建了Thread的匿名类的实现,并重写了run方法,然后启动了线程执行。

问题

上面我们介绍了显式使用Thread创建异步任务的两种方式,但是上述实现方式存在几个问题:

1、每当执行异步任务时,会直接创建一个Thread来执行异步任务,这在生产实践中是不建议使用的,因为线程创建与销毁是有开销的,并且没有限制线程的个数,如果使用不当可能会把系统线程用尽,从而造成错误。在生产环境中一般创建一个线程池,然后使用线程池中的线程来执行异步任务,线程池中的线程是可以被复用的,这可以大大减少线程创建与销毁开销;另外线程池可以有效限制创建的线程个数。

2、上面使用Thread执行的异步任务并没有返回值,如果我们想异步执行一个任务,并且需要在任务执行完毕后获取任务执行结果,则上面这个方式是满足不了的,这时候就需要用到JDK中的Future了。

3、另外,每当需要异步执行时,我们需要显式地创建线程并启动,这是典型的命令式编程方式,增加了编程者的心智负担。我们需要的是声明式的异步编程方式,即告诉程序我们要异步执行,但是具体怎么实现异步应该对我们透明。

异步编程-线程实现异步编程相关推荐

  1. C# 线程知识--异步编程模型(APM)

    在构建高性能.可伸缩的应用程序时,必定会采用异步操作来提升应用程序性能,改善用户体验,异步操作与线程池结合允许使用很少的线程执行许多的操作.CLR中提供了一种异步操作的模式即异步编程模式. 1.异步编 ...

  2. python异步编程视频_asyncio异步编程【含视频教程】

    Python Python开发 Python语言 asyncio异步编程[含视频教程] 不知道你是否发现,身边聊异步的人越来越多了,比如:FastAPI.Tornado.Sanic.Django 3. ...

  3. 浅谈.Net异步编程的前世今生----异步函数篇(完结)

    前言 上一篇我们着重讲解了TPL任务并行库,可以看出TPL已经很符合现代API的特性:简洁易用.但它的不足之处在于,使用者难以理解程序的实际执行顺序. 为了解决这些问题,在C# 5.0中,引入了新的语 ...

  4. 【转】1.6异步编程:IAsyncResult异步编程模型 (APM)

    传送门:异步编程系列目录-- 大部分开发人员,在开发多线程应用程序时,都是使用ThreadPool的QueueUserWorkItem方法来发起一次简单的异步操作.然而,这个技术存在许多限制.最大的问 ...

  5. pythonasyncio并发编程实战_python异步编程之asyncio(百万并发)

    [python异步编程之asyncio(百万并发)] 前言:python由于GIL(全局锁)的存在,不能发挥多核的优势,其性能一直饱受诟病.然而在IO密集型的网络编程里,异步处理比同步处理能提升成百上 ...

  6. springboot异步和切面_Spring异步编程 你的@Async就真的异步吗?异步历险奇遇记

    引言有点长 前端的宝宝会用ajax,用异步编程到快乐的不行~ 我们java也有异步,用起来比他们还快乐~ 我们biaji一个注(gǒupí)解(gāoyào),也是快乐风男... 且看下面的栗子: 注 ...

  7. springboot异步和切面_Spring异步编程 | 你的@Async就真的异步吗 ☞ 异步历险奇遇记...

    引言有点长 前端的宝宝会用ajax,用异步编程到快乐的不行~ 我们java也有异步,用起来比他们还快乐~ 我们bia~ji~一个注(gǒupí)解(gāoyào),也是快乐风男... 且看下面的栗子: ...

  8. springboot异步和切面_Spring异步编程 | 你的@Async就真的异步吗?异步历险奇遇记

    Spring异步编程 | 你的@Async就真的异步吗?异步历险奇遇记 点击上方"java进阶架构师",选择右上角"置顶公众号" 20大进阶架构专题每日送达 引 ...

  9. 【学习笔记】Part1·JavaScript·深度剖析-函数式编程与 JS 异步编程、手写 Promise(二、JavaScript 异步编程)

    [学习笔记]Part1·JavaScript·深度剖析-函数式编程与 JS 异步编程.手写 Promise(课前准备) [学习笔记]Part1·JavaScript·深度剖析-函数式编程与 JS 异步 ...

最新文章

  1. Mac版本Navicat下载
  2. 覆盖索引与联合索引_浅析MySQL的索引覆盖和索引下推
  3. 再议libcurl编程
  4. 有轻功:用3行代码让Python数据处理脚本获得4倍提速
  5. 新浪微博时间格式解析java_仿新浪微博格式化时间
  6. Vysor 2.1.x Pro使用
  7. div+css命名大全
  8. samba (centos6.5)服务
  9. 微信小程序登录流程总结 目录 1.1. 前端调用wx.login 。。给后端传递一个code 1 1.2. 开发者需要在开发者服务器后台调用 auth.code2Session,使用 code 换取
  10. 毕业设计任务书----基于Android的学生考勤管理系统设计与实现
  11. 戴尔r720服务器装爱快路由系统,笔记本虚拟机里安装爱快软路由做单臂路由
  12. 计算机里的游戏怎么输入,如何输入对号(对号怎么打?电脑上和手机分别怎么打?)...
  13. Ceph分布式存储系统优化分析
  14. Element级联菜单省市json数据
  15. AI人工智能代替人工翻译后,我们还需要学习英语吗?
  16. js-PhotoSwipe相册功能
  17. 图像傅里叶变换(快速傅里叶变换FFT)
  18. 【武器系统】【2008.06】海军巡航导弹的制导与控制
  19. WP8.1之小小记事本编程
  20. 使用一根USB线便在电脑上控制树莓派

热门文章

  1. 2021年阿贝尔奖公布!理论计算机科学和离散数学领域学者获奖
  2. 压力测试工具ab介绍
  3. Java-虚拟机原理
  4. Java去除字符串中空格的方法详解
  5. uiautomator2使用教程
  6. C++从零开始区块链:P2P模块之UDP数据包分组排序
  7. scsi设备驱动体系架构
  8. 2021-07-01:并查集,200岛屿问题,547朋友圈问题
  9. linux笔记(7):东山哪吒D1H使用framebuffer画直线(HDMI输出)
  10. RHCSA——第八天