在本教程中,您将:
- 比较同步和异步读取非常大的文件时的速度和内存运用情况。
- 创立和运用自界说
AsyncSequence
. - 创立和运用根据拉的和根据推的
AsyncStream
s。
留意:这是一个中级教程。你应该了解“传统”并发——GCD(Grand Central Dispatch)和URLSession
——以及基本的 Sw面试问题ift 并发线程池的七个参数特性,比方SwiftUI和SwiftUI 中的async/await和结构化并发中呈现的那些特性。
Data Files
ActorSearch的目的是帮助数据结构严蔚敏您经过从IMDb 数据集中查找name.basics.tsv.gz数据集来处理问询艺人名字的难题。该文件包括一个标题行来描绘每个称号的信息:
-
nconst
(字符串)– 名字/人员的字母数字唯一标识符 -
primaryNam面试e
(字符串)– 最常记入此人的名字 -
birthYear
– YYYY 格局 -
deathYear
– 如果适用,采用 YYYY 格局,否则为 ‘N’ -
primaryProfession
(字符串数组)– 人的前三个职业 -
knownForTios模拟器itles
(tconsts 数组)– 此人的闻名头衔
为了减少对您的网络数据结构c语言版第二版课后答案的需求并使其易于逐行阅读,发动项目已经包括data.tsv:这是解压缩的name.basicsios应用商店.tsv.iOSgz,已删去标题行。它是一个制表符分隔值 (TSV) 文件,格局为 UTF-8 字符集。
留线程数越多越好吗意:不要试图经过在项目导航器中挑选它ios下载来检查data.tsv。翻开需求很长时刻,Xcode 变得无呼应http协议。
在本教程中,您将探究将文件线程和进程的区别是什么内容读入值数组的不同办法Actor
。data.tsv包括 11,445,101 行而且需求很长时刻才干读入,因而您将仅运用它来比较内存运用情况。您将在较小的文件data-100.tsv和data-1000.tsv上测验大部分代码,它们别离包括前 100 和 1000 行。
留意:这些文件仅在发动项目中。如果要构建和运转该项目,请将它们复制到终究项目中。
Models
翻开面试问题大全及答案大全ActorAPI.swift。面试自我介绍3分钟通用Actor
是一个超级简略的结构,只要两个属性:id
和name
。
在此文件中,您将完结读取数据文件的不同办法。ActorAPI
初始化程序承受一ios14.4.1更新了什么个参数fiios是什么意思lename
并创立面试问题大全及答案大全.url
它是一个ObservableObject
发布Actor
数组的。
starter 包括一个基本的同步办法:
func readSync () throws {
let start = Date .now
let contents = try String (contentsOf: url)
var counter = 0
contents.enumerateLines { _ , _ in
counter += 1
}
print ( " (counter) lines" )
print ( "持续时刻: (Date.now.timeIntervalSince(start)) " )
}
String
这只是从contentsOf
文件的中创立一个url
,然后核算行数并打印该数字以及花费ios是什么意思了多长时刻。
注:enum数据结构教程第5版李春葆答案erateLines(invoking:)
是从St线程池的七个参数ringProtocol
办法桥接的NSString
办法enumerateLines(_:)
。
View
翻开ContentView.swift。ContentView
创立一个ActorAPI
具有特定文件名的目标并显现该Actor
数组,并带有一个查面试技巧和注意事项找字段。
searchable(https和http的区别text:)
首要,http://192.168.1.1登录在闭包下面增加这个视图修饰符:
.onAppear {
做{
测验model.readSync()
}捕捉 让过错 {
打印(error.localizedDescription)
}
}
您readSync()
在视图呈现时调用,捕获并打印任何r数据结构严蔚敏eadSync()
抛出的过错。
现在,检查运转此应用程序时的内存运用情况。翻开调试导航器,然后构建并运转。当外表呈现时,挑选内存并观看:
在我的 Mac 上,读取这个 685MB 的文件需求 8.9 秒,并产生 1.9GB 的内存运用峰值。
接下来,您将测验一种 Swift 并发办法来读取文件。您将遍历一个异步序列。
AsyncSequence
您Sequence
一直在运用该协议:数组、字典、iOS字符串、范围和Data
都是序列线程和进程的区别是什么。它们带有许多便利的办法,例面试如next()
、contains()
等filter()
。对序列进行循环运用其内线程池置的迭代器,并在迭代器回来时停止nil
。
该AsyncSequence
协议的作业原理类似于Sequence
,但异步序列异步回来每个元素(呃!)。跟着更多元素跟着时刻的推移变得可用,您能够异步迭代其元素。
- 你
await
每个元面试技巧和话术大全素,所以序列能够在获取或核算下一个值时暂停。 - 序列生成元素的速度或许比您的代码运https和http的区别用它们的速度更快:一种
AsyncStream
缓冲其值,因而您的应用程序能够在需求时读取它们。
AsyncSequence
为异步处理数据调集供ios系统给言语支持。有内置的AsyncSequence
s likeNotificationCenter.Notifications
,URLSession.bytes(from:delegate:)
以及它的子序列lines
和cha数据结构严蔚敏racters
。AsyncSequence
您能够运用和AsyncIteratorProtocol
或运用创立自己的自界说异步序列AsyncStream
。
留意:Apple 的As面试yncSequence 文档页面列出了一切内置的异步序列。
Reading a File Asynchronously
为了直接从 URL 处理数据集,URL
基础面试问题大全及答案大全类供给了自己的AsyncSequence
in完结URL.lines
。这关于直接从 URL 创立异步行序列很有http://www.baidu.com用。
翻开ActorAPI.swift并将这个办法增加到ActorAPI
:
// 异步读取
func readAsync () async throws {
let start = Date .now
var counter = 0
for try await _ in url.lines {
计数器+= 1
}
打印(“ (计数器)行”)
print ( "持续时刻:(Date.now.timeIntervalSince(start)) " )
}
您在异步序列上异步迭代,边走边核算行数。
这里有一些 Swift 并发魔法:url.lines
有自己的异步迭代器,for
循环调用它的next()
办法,直到序列线程经过回来nil
.
留意:URLSession
有一个获取异步字节序列和常用URLResponse
目标的办法。您能够检查呼应状况代码,然后调用lines
此字节序列将其数据结构c语言版严蔚敏第二版答案转数据结构c语言版换为异步行序列。
let (stream, response) = try await URLSession .shared.bytes(from: url)
guard (response as? HTTPURLResponse ) ? .statusCode == 200 else {
throw "服务器呼应过错。"
}
for try await line in stream.lines {
// ...
}
Calling anios越狱 Asynchronous Method From a View
要从 SwiftUI 视图调用异步办法,请运用task(priority:_:线程数是什么)
视图修饰iOS符。
在ContentView
中,注释掉onAppear面试技巧和话术大全(perform:)
闭包并增加以下代码:
.task {
做{
测验 等候model.readAsync()
}捕捉 让过错 {
打印(error.localizedDescription)
}
}
翻开调试导航器,然后构建并运转。当外表呈现时,挑数据结构与算法选内存并观看:
在我的 Mac 上,读取文件需求 3.7 秒,内存运用量稳定在 68面试问题大全及答案大全MB。不同很大!
在循环的每次迭代ios越狱中fo面试自我介绍r
,lines
序列都会从 URL 中读取更http://192.168.1.1登录多数据。由于这是分块产生的,所以内存运用量坚持不变。
Getting数据结构知识点总结 Actors
是时分填充actors
数组httpwatch了,这样应用就能ios下载够显现一些东西了。
将此办法增加到Actor数据结构教程第5版李春葆答案API
:
func getActors () async throws {
for try await line in url.lines {
let name = line.components(separatedBy: " t " )[ 1 ]
await MainActor .run {
actor.append(艺人(名字: 名字))
}
}
}
您无需核算行数,而是从每一行中提取称号数据结构有哪些,运用它来创立一个Actor
实例,然后将其附加到actors
.由于acios是苹果还是安卓tors
是 SwiftUI数据结构 视图运用的已发布属性,所数据结构c语言版严蔚敏第二版答案以修改它必须在主队列上进行。
现在,在ContentView
闭task
包中,替换try await model.readAsync()
为:
测验 等候model.getActors()
此外,model
运用较小的数据文件之一更新声明,data-面试问题100.tsv或data-1000.tsv:
@StateObject private var model = ActorAPI (filename: "data-100" )
构建并运转。
该列表很快呈现。下拉屏幕以检查查找字段并测验一些查找。运用模拟器的软件键盘 (Command-K) 能够更轻松地撤销查找词的首字母大写。
Custom AsyncSequence
到目前为止,您一直在运用 URL API 中内置的异步序列。您还能够创立自己的自界说AsyncSequence
,例如AsyncSequence
值Actor
。
要界说一个AsyncSequence
over 数据集,您需数据结构c语言版求遵从其协议并构造一个AsyncIterahttp 500tios16or
回来调集中httpwatch数据序列的下一个元素的 an。
AsyncSequence o数据结构有哪些f Actors
你需求两个结构——一个符合,AsyncSequence
另一个符合AsyncIteratorProtocol
.
在HTTPActorAPI.swift的 outsideActorAPI
中,增加这些最小结构:
struct ActorSequence : AsyncSequence {
// 1
typealias Element = Actor
typealias AsyncIterator = ActorIterator
// 2
func makeAsyncIterator () -> ActorIterator {
return ActorIterator ()
}
}
struct ActorIterator : AsyncIteratorProtocol {
// 3
mutating func next () -> Actor ? {
回来 零
}
}
留意:如果您乐意,能够在结构内部界说迭代器结构AsyncSequence
。
以下是此代码的每个部分的作用:
- 你
AsyncSeqhttps和http的区别uence
生成一个Element
序列。在这种情况下,ActorSeqios系统uence
是Actor
s 的序列。AsyncSequence
期望一个AsyncIterator
,你typealias线程和进程的区别是什么
要ActorIterator
。 - 该
AsyncSequence
协议需求一个makeAsyncIterator()
办法,该办法回来一个ActorIterator
.此办法不能包括任何异步或抛出代码。像这样的代码进入ActorIterator
. - 该
Ashttp协议yncIteratorProtocol
协议需求一个面试自我介绍一分钟next()
办法来回来下一个序列元素,或许nil
, 来表示序列的完毕。
现在,要填写结构,请将这些行增加到ActorSequ面试技巧ence
:
让文件名:字符串
让网址:网址
init(文件名:字符串){
self .filename =文件名
self .url = Bundle .main.url(forResource:文件名,withExtension:“tsv”)!
}
该序列需求文件名的参数和存储文件 URL 的属性。您在初始化程序中设置这些。
在makeAsyncIterator()
中,您将遍历uHTTPrl.lines
。
将这些行增加到ActorIterator
:
让url: URL
var迭代器: AsyncLineSequence < URL . 异步字节>。异步迭代器
初始化(网址:网址){
self .url = url
迭代器= url.lines.makeAsyncIterator()
}
您显式地获取了异步迭代器,url.lines
因而next()
能够调用迭代器https和http的区别的next()
办法。
现在,修正ActorItios14.4.1更新了什么erator()
调用makeAsyncios模拟器Iterator()
:
回来 ActorIterator (url: url)
接下来,替换next()
为以下内容:
变异 func next () async -> Actor?{
do {
if let line = try await iterator.next(), ! line.isEmpty {
let name = line.components(separatedBy: " t " )[ 1 ]
return Actor (name: name)
}
}捕捉 让过错 {
打印(error.localizedDescription)
}
回来 零
}
您将asyn面试自我介绍简单大方c
关键字增加到签名中,由于此办法运用异步序列迭代器。只是为了改动,你在这里处理http://192.168.1.1登录过错而不是数据结构c语言版抛出它们。
现在线程数是什么,在 中ActorAPI
,修改getActors()
以运用此自界说AsyncSequence
:
func getActors () async {
for await actor in ActorSequence ( filename : filename ) {
await MainActor .run {
艺人.追加(艺人)
}
}
}
处理任何过错的next()
办法,因而不会抛出,而且您不必处理.ActorIhttp代理terator``getActors()``try await``ActorSequ面试自我介绍3分钟通用ence
您迭代Actor面试自我介绍3分钟通用Sequence(filename:)
,它回来Actor
值供您附加到actors
.
终究,在 中ContentView
,将task
闭包替换为:
.task {
等候模型.getActors()
}
代码要简略得多,现在getActors()
不会抛出。
构建并运转。
一切都相同。
AsyncStream
自界说异步序列的唯一缺点是需求创立和命名结构,这会增加到应用程序的命名空间中。AsyncStream
让您“即时”创立异步序列。
typealias
您只需运用元素类型初始化您的,而不是运用 a ,AsyncStr面试eam
然后在其尾随闭包中创立序列。
其实有两种AsyncStream
。一个有unfolding
闭包。像AsyncIterator
,它供给next
元素。它只在使命要求一个值时创立一系列值,一次一个。将其视为根据拉动或需求驱动的。
AsyncStream: Pullhttpclient-based
首要,您将创立根据拉取AsyncStream
的ActorAsyncSequence
.
将此办法增加到ActorAPI
:
// AsyncStream: 根据拉取的
func pullActors () async {
// 1
var iterator = url.lines.makeAsyncIterator()
// 2
let actorStream = AsyncStream < Actor > {
// 3
do {
if let line = try await iterator.next(), ! line.isEmpty {
let name = line.components(separatedBy: " t " )[ 1 ]
return Actor (name: name)
}
}捕捉 让过错 {
打印(error.localizedDescription)
}
回来 零
}
// 4
for await actor in actorStream {
await MainActor .run {
艺人.追加(艺人)
}
}
}
这是您运用此代码所做的作业:
- 您依然创立一个
AsyncIterator
forurl.lines
。 - 然后你创立一个
AsyncStream
,指定Element
类型Actor
。 -
next()
并将办法的内容复制ActorIterator
到闭包中。 - 现在数据结构知识点总结,
actorStream
是一个异步序列,与 完全相同ActorSequence
,因而您能够像在getActors()
.
在Contios14.4.1更新了什么entView
中,调用pullActors()
而不是getActors()
:
等候模型.pullActors()
构建并运转,然后检查它是否依然能够正常作业。
AsyncStream: Push-based
另一种AsyncStream
有build
闭包。它创立一系列值并缓冲它们,直到有人要求它们为止。将其视为根据推送或供给驱动的。iOS
将此办法增加到ActorA数据结构PI
:
// AsyncStream: 根据推送的
func pushActors () async {
// 1
let actorStream = AsyncStream < Actor > { continuation in
// 2
Task {
for try await line in url.lines {
let name = line.components(separatedBy: " t " )[ 1 ]
// 3
continuation.yield( Actor (name: name))
}
// 4
连续.finish()
}
}
关于 actorStream中的等候 艺人 {
await MainActor .run {
艺人.追加(艺人)
}
}
}
这是您在此办法中所做的作业:
- 您ios15不需求创立迭代器。相反,您会得到一个
continuation
. -
build
闭包不是异步的数据结构严蔚敏,因而您必须在Task
异步序列上创立一个 to 循环url.lines
。 - 关于每数据结构知识点总结一ios模拟器行,您调用连续的
yield(_:)
办法线程池的七个参数将Actor
值推入缓冲区。 - 当你抵达结尾时
url.lines
,你调用连续的finish()
办法。
留意:由于build
闭包不是异步的,所以你能够运用这个版本AsyncStream
来与非异步http协议 API 交互,比方fread(_:_:_:_:HTTP)
.
在ContentView
中,调用pushActors()
而不是pullActors()
:
等候模型.pushActors()
构建并运转并承认它能够作业。
Continuations
自 Apple 首次推出 Grand Central Dispatch 以http://192.168.1.1登录来,它就向开发人员供给了怎么避免线程爆破风险的建议。
当线程多于 CPU 时,调度程序在线程之间分时同享 CPU线程数越多越好吗,履行上下文切换以换出正在运转的线程并换入堵塞的线程。每个线程都有一个堆栈和相关的内核数据结构,因而上下文切换需求时刻。
当应用程序创立大量线程时——例如,当它下载成百上千张图画线程撕裂者时——CPU面试问题 会花费太多时刻进行上下文切换,而没有足够的时刻做有用的作业。
在 Swift 并发体系中,线程的数量最多只要 CPU 的数量。
当线程池面试题线程在 Swift 并发下履行作业时,体系运用一个HTTP称为continuation的轻量级目标来盯梢在何处康复暂停使命的作业。在使命连续之间切换比履行线程ios应用商店上下文切换更便宜、更有效。
留意:这个带有连续的线程图画来自 WWDC21 Session 10254。
当使命挂起时,它会持续捕获其状况。它的线程能够康复另一个使命的ios越狱履行,从它挂起时创立的连续中从头创立它的状况。这样做的代价是函数调用。
async
当您线程池运用函数时,这一线程数是什么切都产生在幕后。
可是您也能够持续手动康复履行。的缓冲形式AsyncStream
运用连续来yiios15eld
流式传输元素。
不同的连续 API 可帮助您重用现有代码,如完结处理程序和托付办法。要了解怎么操作,请检查Swhttp 500ift 中的现代并发,第 5 章,“中心 async/await 和 CheckedContinuation”。
Push or Pull?数据结构
Push-based 就像工厂制造衣服并将它们存储在仓库或商店中,直到有人购买它们。Pull-bas线程是什么意思ed 就像从裁缝那里订购衣服。
在根据拉取和根据推送之间进行挑选时,请考虑与您的用例的潜在不匹配:
- 根据拉的(展开)
AsyncStream
:您的代码需求比异步序列更快的值。 - 根据推送(缓冲)
AsyncStream
:异步序列生成元数据结构c语言版第二版课后答案素的速度比您的代码读取它们的速度更快,或许以不规则或不行预测的时刻间隔生成元素,例如来自后台监视器的更新——告诉、位置、自界说监视httpwatch器
下载大文件时,根据拉取的办法AsyncStream
(仅在代码恳求时才下载更多字节)数据结构与算法能够让您更好地控制内存和网ios15络运用。根据推送(AsyncStream
不暂停下载整个ios是苹果还是安卓文件)或许会导致内存或网络运用量激增。
要了解这两种 . 的面试自我介绍一分钟另一个差异Async数据结构教程第5版李春葆答案Stream
,请检查如果您的代码不运用actorStream
.
在和ActorAPI
中注httpwatch释掉这段代码:pullAhttp 404ctors()``pushActors()
关于 actorStream中的等候 艺人 {
await MainActor .run {
艺人.追加(艺人)
}
}
接下来,在这两种办法中的这一行放置断点:
let name = line.components(separatedBy: " t " )[ 1 ]
编辑两个断点以记载iOS断点称号和命中计数,然后线程的几种状态持续:
现在,在 中ContentView
,设置task
为调用p面试自我介绍简单大方ullActors()
:
.task {
等候模型.pullActors()
}
构建并运转,然后翻开调试控制台:
actorStream
不会呈现日志消息,由于当您的代码不要求其元ios是什么意思素时,根据拉取的代码不会运转。除非您要求下一个元素,否则它不会从文件中读取。
现在,切换task
到调用pushActors()
:
.task {
等候模型.pushActors()
}
构建并数据结构c语言版第二版课后答案运转,翻开调试控ios模拟器制台:
actorStream
即便您的代数据结构教程第5版李春葆答案码不要求任何元素,根据推送的也会运转。它读取整个文件并缓冲序列元素。
Conclusion
留意:数据文件仅在发动项目中。如果要构建和ios14.4.1更新了什么运转该项目,请将它们复制到终究项目中。
在本教程中,您:
- 比较了同步和异步读取非常大的文件时的速度和内存运用情况。
- 创立并运用了自界说
AsyncSequence
. - 创立并运用了根据拉的和根据推的
AsyncStream
s。 - 表明在
AsyncStream
代码恳求序列元素之前,根据拉的程序什么都不做,而根据推送的程序AsyncStream
不管代码是否恳求序列元数据结构严蔚敏素都运转。
您能够运用AsyncSequen数据结构实验报告ce
和AsyncStream
从现有代码生成异步序列——您屡次调用的任何闭包,以及只报告新值且不需求回来呼应的托付ios15办法。
下载项目材料与原文地址
这里也引荐一些面试相关的内容!数据结构
-
① BAT等各个大厂iOS面试真题+答案大全数据结构c语言版第二版课后答案
-
② iOS中高级开发必看的抢手书籍(经典必看)
-
③ iOS开发高级面试线程是什么意思“简历制作”线程数越多越好吗辅导
-
④ iOS面试流程到基础知识大全