专栏首页丑胖侠一篇文章,搞懂异步和多线程的区别

一篇文章,搞懂异步和多线程的区别

最近在研究Spring Boot中的异步处理,发现涉及到异步和多线程的很多知识点,就先写几篇关于异步与多线程的文章,带大一起回顾或学习一下相关的知识点。下面开始正文内容:

前言

在本文中,我们通过一些通俗易懂的方式来解释异步编程和多线程编程,然后再介绍一下它们之间的区别。

什么是异步编程

首先来看一下异步模型。在异步模型中,允许同一时间发生(处理)多个事件。程序调用一个耗时较长的功能(方法)时,它并不会阻塞程序的执行流程,程序会继续往下执行。当功能执行完毕时,程序能够获得执行完毕的消息或能够访问到执行的结果(如果有返回值或需要返回值时)。

下面通过一个示例来看一下同步和异步的区别。示例中程序通过网络获取两个文件,并对两个文件进行合并处理:

上述示例,在异步系统当中的解决方案是开启一个额外的线程进行处理。第一个线程获取第一个文件,第二个线程获取第二个文件,第二个线程并不需要等待第一个线程执行完毕再执行。当两个线程都获得到对应的结果之后,再重新同步处理合并结果的操作。

再来看另外一个场景。单线程方法读取OS(操作系统)当中的文件并需要进行数学运算。而在异步系统中,程序发起读取OS中文件的请求,由于读取操作比较耗时,在等待读取文件时,程序会将控制器返回给CPU进行数学运算。

在异步编程中,通常会针对比较耗时的功能提供一个函数,函数的参数中包含一个额外的参数,用于回调。而这个函数往往称作回调函数。当比较耗时的功能执行完毕时,通过回调函数将结果返回。关于回调函数相关的知识可参考文章《两个经典例子让你彻底理解java回调机制》。

什么是多线程编程

多线程是指同时并发或并行执行多个指令(线程)。

在单核处理器上,多线程往往会给人程序是在并行执行的错觉。实际上,处理器是通过调度算法在多线程之间进行切换和调度。或者根据外部输入(中断)和线程的优先级的组合来进行线程的切换。

在多核处理器上,线程才是真正的并行运行。多个处理器同时执行多个线程,以达到更加高效的处理。

一个简单的示例就是:开启两个浏览器窗口同时下载两个文件。每个窗口都使用一个新的线程去下载文件,它们之间并不需要谁等待谁完成,而是并行进行下载。

下图展示了并发执行多线程应用程序的流程:

异步与多线程的区别

通过上面的介绍,我们可以看出多线程都是关于功能的并发执行。而异步编程是关于函数之间的非阻塞执行,我们可以将异步应用于单线程或多线程当中。

因此,多线程只是异步编程的一种实现形式。

比如,你和你的朋友决定一起做一顿午餐。“异步”就是你对朋友说:“你去商店买意大利面,回来的时候告诉我一声,然后一起做午餐。在你买意大利面的同时,我去准备番茄酱和饮料。”

而“线程”是:“你烧水,我加热番茄酱。当水烧开了,告诉我,我把意大利放进去。当番茄酱热了,你可以把奶酪添加进去。当两者都完成了,就可以坐下来一起吃晚餐。”在线程的示例中,我们可以看到“When,Do”的事件顺序,而这些顺序代表着每个人(线程)的指令集集合的顺序。

上述示例可以看出,多线程是与具体的执行者相关的,而异步是与任务相关的。

多线程是程序设计的逻辑层概念,它是进程中并发运行的一段代码,可以实现线程间的切换执行。

异步和同步是相对的,异步就是彼此独立,在等待某事件的过程中继续做自己的事,不需要等待这一事件完成后再工作。

多线程就是实现异步的一个方式。异步是让调用方法的主线程不需要同步等待另一线程的完成,从而可以让主线程干其它的事情。

所以本质上,异步和多线程并不是一个同等关系,异步是最终目的,多线程只是实现异步的一种手段。

如何选择

面对多线程和异步,我们该如何选择呢?其实,通常情况下选择的依据是主要取决于性能。

那么,同步/异步与单线程/多线程之间的所有组合,哪种模型表现更好?

简而言之,对于具有大量I/O操作和不同计算的大规模应用程序,使用异步多线程有利于充分利用计算资源,并且能够照顾到非阻塞函数。这也是所有操作系统所采用的线程模型。

编写异步操作的复杂程度较高,程序主要使用回调方式进行处理,与正常的思维方式有些出入,而且难以调试。而多线程的使用(滥用)会给系统带来上下文切换的额外负担,并且线程间的共享变量可能造成死锁。

因此在实现这两种模式时,往往需要处理资源竞争、死锁、共享资源和回调事件等问题。

小结

在本文中,我们讲解了异步编程和多线程编程的定义,然后是它们之间的区别。而本文中的所有术语和概念均与具体技术实现无关。后面我们会继续讲解多线程与异步相关的其他知识点,比如异步调用与回调等。

原文链接:《一篇文章,搞懂异步和多线程的区别


程序新视界 公众号“ 程序新视界”,一个让你软实力、硬技术同步提升的平台,提供海量资料

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 一篇文章搞懂Python多线程简单实现和GIL

    今天开始打算开一个新系列,就是python的多线程和多进程实现,这部分可能有些新手还是比较模糊的,都知道python中的多线程是假的,但是又不知道怎么回事,首先...

    南山烟雨
  • 干货丨一篇文章读懂H5/App/小程序的区别

    如何让自己的想法通过合适的产品实现更好的落地,前提是要清楚不同工具的特点,关于H5和APP以及小程序的概念介绍已经有了很多,接下来会详细介绍三者之间的开发区别和...

    齿轮易创说互联网
  • 一篇文章搞明白Integer、new Integer() 和 int 的概念与区别

    1、Integer 是 int 的包装类,int 则是 java 的一种基本数据类型

    程序员追风
  • 一篇文章读懂SaaS多租户和单租户的分别

    提到SaaS,很多人都会立刻想到节约成本、按需付费、即租即用等等这些概念,这说明大部分人对SaaS已经有了普遍认知,且开始主动应用SaaS软件。然而这只是一些浅...

    8Manage企业管理软件
  • 一篇文章帮你彻底搞清楚“I/O多路复用”和“异步I/O”的前世今生

    曾经的VIP服务 在网络的初期,网民很少,服务器完全无压力,那时的技术也没有现在先进,通常用一个线程来全程跟踪处理一个请求。因为这样最简单。 其实代码实现大...

    Java团长
  • 一篇文章帮你彻底搞清楚“I/O多路复用”和“异步I/O”的前世今生

    可以看到服务器端确实为每个连接创建一个线程,共创建了20个线程。 客户端进入休眠约5-10秒,模拟连接上数据不就绪,服务器端线程在等待,等待时间约5-10秒。...

    Java3y
  • 2019 最新 Java 核心技术教程,都在这了!

    以下是Java技术栈微信公众号发布的所有关于 Java 的技术干货,会从以下几个方面汇总,本文会长期更新。

    Java技术栈
  • 一篇文章理清Python多线程同步锁,死锁和递归锁

    但是不知道大家有没有注意到一点就是前面说的两个功能是相互独立的,相互不干涉的,不会用到同享的资源或者数据,如果我们多个线程要用到相同的数据,那么就会存在资源争用...

    南山烟雨
  • 深度|一篇文章搞懂人工智能、机器学习和深度学习之间的区别

    2015年11月9日,Google发布人工智能系统TensorFlow并宣布开源。这两年在不管在国内还是在国外,人工智能、机器学习仿佛一夜之前传遍大街小巷。 概...

    灯塔大数据

扫码关注云+社区

领取腾讯云代金券