异步和多线程_您应该使用哪个:异步编程或多线程?

差异,常见误解和Python示例

c8e1f03bed3f819b11cf1f0e41468a73.png

> Image source: Author

当涉及到软件工程时,这两个概念通常会有些混乱。 它们都是并发形式,但是它们并不意味着同一件事,并且不会以相同的方式应用或在相同的场景中使用。

简单的解释是线程与工人有关。 异步与任务有关。 但是,让我们来探讨一下。

类似地,假设我们要煮鸡蛋和吐司的早餐。 我们将如何做?

同步方式

最简单的方法是依次执行:

· 取出鸡蛋,面包和锅,然后打开火炉。

· 裂开鸡蛋,将它们倒入锅中。

· 等待鸡蛋完成烹饪。

· 取出鸡蛋并加入调味料。

· 将面包放入烤面包机。

· 等待烤面包机完成。

· 拿出烤面包。

早餐总时间:15分钟。

很简单吧? 如果我们说以这种方式烹饪鸡蛋类似于执行程序,那就是说这是一种同步烹饪鸡蛋的方法。

我们有一个人按顺序(序列化)来完成所有任务。 我们正在按顺序进行每个步骤,如果没有完成最后一步,就无法继续进行下一步。 从技术上来说,更严格的定义是,上一步禁止执行每个任务,而所有任务都是由一个工人完成的。 不走最后一步,我们就无法前进。 在此示例中,我们是计算机的中央处理器或CPU。 每个完成的任务都由一个人(一个CPU)完成。

05c69482bb2a1bf4778ea3262ffdc26d.png

> Single-threaded synchronous way to cook breakfast

好的,我们煮鸡蛋了。 但是,如果我们想让我们的早晨更快些呢? 您可能对自己说:"我不等我的鸡蛋吃完了再烤面包。"

您现在想像工程师一样。 让我们再试一次,但是这次,我们决定要同时煮鸡蛋和烤面包,并默默地感谢烤面包计时器的发明者。

异步方式

我们仍然可以让一个人做所有事情,但是我们可以在等待另一项任务完成的同时完成另一项任务。 看起来像这样:

· 取出鸡蛋,面包和锅,然后打开火炉。

· 裂开鸡蛋,将它们倒入锅中。

· 等待鸡蛋完成烹饪。

· 将面包放入烤面包机。

· 等待烤面包机完成。

· 鸡蛋煮熟后,取下鸡蛋,并添加调味料。

· 烤面包完成后,取出烤面包。

早餐总时间:八分钟。

看起来就像所有相同的步骤,对不对? 除了一项重大升级。 在等待鸡蛋完成的过程中,我们将烤面包放进去,而不是完成鸡蛋并继续烤面包。 我们仍然只有一名工人来完成所有任务,但是现在他们是异步进行的。 现在似乎只有两个任务可以异步完成,您可以想象拥有数千个鸡蛋和烤面包以及数千个煎锅和烤面包机如何一次完成每个任务都是荒谬的!

这是异步工程的最大优点之一。 通常,我们不得不等待无法控制的动作完成。 在这种情况下,它正在等待鸡蛋和吐司做饭。 我们可以拥有这个星球上最高效,最好的厨师,但是在大多数情况下,这些鸡蛋只需要坐着等待完成即可。 等待这些准备工作类似于输入/输出(I / O),当我们在等待大量I / O的情况下构建东西时,是使用异步编程的好时机。

如果我们进行API调用,必须从用户那里获得输入等,无论我们拥有多少处理器或计算机有多快,我们都必须等待。 我们必须等待API调用完成,等待用户输入信息。 这是我们无法控制的,并且不会变得更快或专用资源会对其产生任何影响。

734c60872812cad4443e2231b104b8a0.png

> Single-threaded asynchronous way to cook breakfast

赞! 现在,我们有两种制作鸡蛋的方法。 但是,可以说我们的室友凯文(Kevin)想帮忙做鸡蛋。 看起来像什么?

多线程方法

· 取出鸡蛋,面包和锅,然后打开火炉。

· 裂开鸡蛋,将它们倒入锅中。 凯文把面包放进烤面包机。

· 等待鸡蛋完成烹饪。 2.凯文等待烤面包结束。

· 取出鸡蛋并加入调味料。 3.凯文(Kevin)吐司。

早餐总时间:八分钟。

我们有两个人做早餐,每个人分配一个任务序列。 这是同步多线程的一个示例,因为您和Kevin都不会一次执行多个任务(包括等待)。

在计算机科学中,一个进程可以具有一个或多个线程。 在这种情况下,我们有两个线程(人员)。 您可以在此处了解有关线程的更多信息。

您可能会说:"好吧,如果周围有两个人,我只能和两个人一起做早餐。" 电脑也一样。 如果计算机有足够的资源,则只能使用多线程。 当某些任务的计算复杂度更高,需要更多资源或出于其他多种原因时,通常会使用多线程。

0f7fc4bd3bbedb416ef612885c6836f8.png

> Multi-threaded synchronous way to cook breakfast

那么,多线程还是异步是更好的选择? 这确实取决于很多因素,但是如果您了解它们的工作原理,那么应该可以使您对使用哪种方法有一些了解。 它有很多I / O吗? 也许尝试异步。 它是计算密集型的吗? 也许尝试多线程。 编写多线程应用程序要比异步应用程序(取决于语言)要容易得多,但是要记住这一点。 您可以构建多线程异步系统吗? 当然! 经常将这两者相互串联使用。

Python范例

让我们看看上面的三个示例(单线程同步,单线程异步和多线程同步)在Python示例中如何工作。

让我们看看使用Python包装器pip install alpha_vantage从Alpha Vantage API获取库存数据的几种不同方法

同步

我们希望获得四种价格的当前价格,即'AAPL','GOOG','TSLA','MSFT',并仅在我们拥有全部四个时才打印出来。 最简单的方法是使用for循环。

from alpha_vantage.timeseries import TimeSerieskey = 'API_KEY'symbols = ['AAPL', 'GOOG', 'TSLA', 'MSFT']results = []for symbol in symbols:    ts = TimeSeries(key = key)    results.append(ts.get_quote_endpoint(symbol))print(results)

这是最强力的方式。 一旦从API调用中获得一个值(在ts.get_quote_endpoint(symbol)中完成),我们就将其打印出来,然后开始下一个符号。

但是在学习了异步和多线程之后,我们知道可以在等待返回值的同时启动另一个API调用。

异步

在Python中,关键字await和async赋予了我们异步编程的新功能。 这些是Python 3.5的新功能,因此如果您仍在使用Python 2,则需要进行更新。无论如何,很多Python 2都已被贬值,因此请进行更新。

import asynciofrom alpha_vantage.async_support.timeseries import TimeSeriessymbols = ['AAPL', 'GOOG', 'TSLA', 'MSFT']async def get_data(symbol):    ts = TimeSeries()    data, _ = await ts.get_quote_endpoint(symbol)    await ts.close()    return dataloop = asyncio.get_event_loop()tasks = [get_data(symbol) for symbol in symbols]group1 = asyncio.gather(*tasks)results = loop.run_until_complete(group1)print(results)

关于这里发生的事情可能有些混乱,所以让我们分解一下。 循环是处理器在等待任务和执行其他任务之间不断循环的地方。 这是为了继续检查任务(例如API调用)是否已完成。

任务变量是方法调用的列表。 我们将这些任务放在asyncio的聚集列表中,称为group1,然后在loop.run_until_complete中运行它们。 这比我们原始的同步版本快得多,因为我们可以进行多个API调用,而无需等待每个API完成。

注意:Asyncio在Python笔记本中很奇怪,请参阅此处以获取更多信息。

多线程

我已经写了一些有关多线程的文章,因此,如果您想学习更多并看到一些Python示例,请查看此链接以了解更多信息!

还有其他几层需要学习,例如什么是并行性,每个应用程序的更深层次的交互,如何同步线程,通道以及每种语言如何以不同的方式处理它们。

想我错过了什么吗? 什么都不懂 在下面留下问题,评论或见解!

(本文翻译自Patrick Collins的文章《Which Should You Use: Asynchronous Programming or Multi-Threading?》,参考:https://medium.com/better-programming/which-should-you-use-asynchronous-programming-or-multi-threading-7435ec9adc8e)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值