当同步/异步与串行/并发队列混合时,调度程序如何工作?

2024-02-16

在 Grand Central Dispatch 中,调度程序如何处理不同的队列(serial and concurrent)当使用dispatch_sync函数和dispatch_async功能?


首先我们需要两种类型queue: one serial和一个同时:

dispatch_queue_t serialQueue =
dispatch_queue_create("com.matteogobbi.dispex.serial_queue", DISPATCH_QUEUE_SERIAL);

dispatch_queue_t concurrentQueue =
dispatch_queue_create("com.matteogobbi.dispex.concurrent_queue", DISPATCH_QUEUE_CONCURRENT);

所以,我们可以从第一个实验开始,使用串行队列和所有dispatch_async函数将我们的块添加到队列中:

/* Dispatch async with serial queue */
NSLog(@"\n\nDISPATCH: Async - QUEUE: Serial");

NSLog(@"block 1 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 1");
});

NSLog(@"block 2 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 2");
});

NSLog(@"block 3 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 3");
});

NSLog(@"block 4 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 4");
});

NSLog(@"block 5 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 5");
});

NSLog(@"block 6 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 6");
});

NSLog(@"block 7 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 7");
});

NSLog(@"block 8 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 8");
});

NSLog(@"block 9 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 9");
});

NSLog(@"block 10 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 10");
});

NSLog(@"ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED");

调度:异步 - 队列:串行

2014-04-08 14:43:16.468 dispex[4346:60b] 添加块 1

2014-04-08 14:43:16.468 dispex[4346:60b] 块 2 添加

2014-04-08 14:43:16.468 dispex[4346:1303] 块 1

2014-04-08 14:43:16.469 dispex[4346:1303] 块 2

2014-04-08 14:43:16.468 dispex[4346:60b] 块 3 添加

2014-04-08 14:43:16.469 dispex[4346:1303] 块 3

2014-04-08 14:43:16.469 dispex[4346:60b] 块 4 添加

2014-04-08 14:43:16.469 dispex[4346:1303] 块 4

2014-04-08 14:43:16.469 dispex[4346:60b] 块 5 添加

2014-04-08 14:43:16.470 dispex[4346:60b] 块 6 添加

2014-04-08 14:43:16.470 dispex[4346:1303] 块 5

2014-04-08 14:43:16.471 dispex[4346:60b] 添加了块 7

2014-04-08 14:43:16.471 dispex[4346:1303] 块 6

2014-04-08 14:43:16.471 dispex[4346:1303] 块 7

2014-04-08 14:43:16.471 dispex[4346:60b] 块 8 添加

2014-04-08 14:43:16.471 dispex[4346:1303] 块 8

2014-04-08 14:43:16.471 dispex[4346:60b] 添加了第 9 块

2014-04-08 14:43:16.472 dispex[4346:60b] 块 10 添加

2014-04-08 14:43:16.472 dispex[4346:1303] 块 9

2014-04-08 14:43:16.472 dispex[4346:1303] 块 10

2014-04-08 14:43:16.472 dispex[4346:60b] 所有块都添加到队列中 --> 函数返回

如您所见,该块已添加到队列中,但是同时调度员开始执行它们。这是一个特点dispatcher_async函数,即将块添加到队列中,无需等待它们完成执行。换句话说,如果您正在使用dispatch_async在函数中,函数立即返回,同时块正在执行。这非常有用!在此示例中,我使用 NSLog 来报告块何时添加到队列中,因此这确实会导致执行速度变慢并导致日志

添加了所有块

在最后。但正如我们稍后将看到的,如果没有日志,它将被写在开头。由于我们使用的是串行队列,因此块按照添加的顺序执行。

Next:

/* Just wait before begin with the next test */
dispatch_group_wait(group_async_serial, DISPATCH_TIME_FOREVER);


/* Dispatch sync with serial queue */
NSLog(@"\n\nDISPATCH: Sync - QUEUE: Serial");

NSLog(@"block 1 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 1");
});

NSLog(@"block 2 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 2");
});

NSLog(@"block 3 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 3");
});

NSLog(@"block 4 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 4");
});

NSLog(@"block 5 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 5");
});

NSLog(@"block 6 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 6");
});

NSLog(@"block 7 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 7");
});

NSLog(@"block 8 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 8");
});

NSLog(@"block 9 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 9");
});

NSLog(@"block 10 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 10");
});

NSLog(@"ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED");

调度:同步 - 队列:串行

2014-04-08 14:43:16.473 dispex[4346:60b] 块 1 添加

2014-04-08 14:43:16.474 dispex[4346:60b] 块 1

2014-04-08 14:43:16.474 dispex[4346:60b] 块 2 添加

2014-04-08 14:43:16.474 dispex[4346:60b] 块 2

2014-04-08 14:43:16.475 dispex[4346:60b] 块 3 添加

2014-04-08 14:43:16.475 dispex[4346:60b] 块 3

2014-04-08 14:43:16.475 dispex[4346:60b] 块 4 添加

2014-04-08 14:43:16.475 dispex[4346:60b] 块 4

2014-04-08 14:43:16.476 dispex[4346:60b] 块 5 添加

2014-04-08 14:43:16.476 dispex[4346:60b] 块 5

2014-04-08 14:43:16.476 dispex[4346:60b] 块 6 添加

2014-04-08 14:43:16.477 dispex[4346:60b] 块 6

2014-04-08 14:43:16.477 dispex[4346:60b] 块 7 添加

2014-04-08 14:43:16.477 dispex[4346:60b] 块 7

2014-04-08 14:43:16.477 dispex[4346:60b] 块 8 添加

2014-04-08 14:43:16.478 dispex[4346:60b] 块 8

2014-04-08 14:43:16.478 dispex[4346:60b] 添加了第 9 块

2014-04-08 14:43:16.478 dispex[4346:60b] 块 9

2014-04-08 14:43:16.479 dispex[4346:60b] 块 10 添加

2014-04-08 14:43:16.479 dispex[4346:60b] 块 10

2014-04-08 14:43:16.479 dispex[4346:60b] 所有块都添加到队列中 --> 函数返回

在这个例子中我们使用dispatch_sync函数与串行队列。很容易看出,当前一个块执行完毕时,所有块都会被添加。这是一个特点dispatch_sync。换句话说,直到块执行完毕后,该函数才会返回。由于这是一个串行队列,因此这里的顺序也受到尊重。

Next:

/* Dispatch async with concurrent queue */
NSLog(@"\n\nDISPATCH: Async - QUEUE: Concurrent");
dispatch_group_t group_async_concurrent = dispatch_group_create();

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 1");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 2");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 3");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 4");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 5");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 6");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 7");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 8");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 9");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 10");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 11");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 12");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 13");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 14");
});

NSLog(@"ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED");

调度:异步 - 队列:并发

2014-04-08 14:43:16.480 dispex[4346:60b] 所有块都添加到队列中 --> 函数返回

2014-04-08 14:43:16.480 dispex[4346:1303] 块 1

2014-04-08 14:43:16.480 dispex[4346:3503] 块 2

2014-04-08 14:43:16.480 dispex[4346:3603] 块 3

2014-04-08 14:43:16.480 dispex[4346:3803] 块 5

2014-04-08 14:43:16.480 dispex[4346:3703] 块 4

2014-04-08 14:43:16.480 dispex[4346:3903] 块 6

2014-04-08 14:43:16.480 dispex[4346:3a03] 块 7

2014-04-08 14:43:16.480 dispex[4346:3b03] 块 8

2014-04-08 14:43:16.482 dispex[4346:1303] 块 9

2014-04-08 14:43:16.483 dispex[4346:3503] 块 10

2014-04-08 14:43:16.483 dispex[4346:3803] 块 12

2014-04-08 14:43:16.483 dispex[4346:3703] 块 13

2014-04-08 14:43:16.483 dispex[4346:3903] 块 14

2014-04-08 14:43:16.483 dispex[4346:3603] 块 11

正如我之前所说,这里我展示了如何工作dispatch_async但有一个并发队列。 这真的很有趣,因为没有 NSLog 显示何时添加块,您可以看到在执行第一个块之前如何添加所有块。这种行为不是恒定的. 可能会发生 block1 被执行并且紧随其后dispatch_asyncfinish将所有块添加到队列中,然后继续执行其他块。另一件需要注意的事情是,块是并发执行的,因此它们不遵守添加顺序,而且这种行为不是恒定的,而是取决于 CPU 使用率、性能和许多其他因素。

Next:

/* Just wait before begin with the next test */
dispatch_group_wait(group_async_concurrent, DISPATCH_TIME_FOREVER);


/* Dispatch sync with concurrent queue */
NSLog(@"\n\nDISPATCH: Sync - QUEUE: Concurrent");

NSLog(@"block 1 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 1");
});

NSLog(@"block 2 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 2");
});

NSLog(@"block 3 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 3");
});

NSLog(@"block 4 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 4");
});

NSLog(@"block 5 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 5");
});

NSLog(@"block 6 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 6");
});

NSLog(@"block 7 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 7");
});

NSLog(@"block 8 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 8");
});

NSLog(@"block 9 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 9");
});

NSLog(@"block 10 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 10");
});

NSLog(@"ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED");

调度:同步 - 队列:并发

2014-04-08 14:43:16.486 dispex[4346:60b] 块 1 添加

2014-04-08 14:43:16.486 dispex[4346:60b] 块 1

2014-04-08 14:43:16.487 dispex[4346:60b] 块 2 添加

2014-04-08 14:43:16.487 dispex[4346:60b] 块 2

2014-04-08 14:43:16.487 dispex[4346:60b] 块 3 添加

2014-04-08 14:43:16.488 dispex[4346:60b] 块 3

2014-04-08 14:43:16.488 dispex[4346:60b] 块 4 添加

2014-04-08 14:43:16.488 dispex[4346:60b] 块 4

2014-04-08 14:43:16.489 dispex[4346:60b] 块 5 添加

2014-04-08 14:43:16.489 dispex[4346:60b] 块 5

2014-04-08 14:43:16.489 dispex[4346:60b] 块 6 添加

2014-04-08 14:43:16.489 dispex[4346:60b] 块 6

2014-04-08 14:43:16.490 dispex[4346:60b] 块 7 添加

2014-04-08 14:43:16.490 dispex[4346:60b] 块 7

2014-04-08 14:43:16.490 dispex[4346:60b] 块 8 添加

2014-04-08 14:43:16.491 dispex[4346:60b] 块 8

2014-04-08 14:43:16.491 dispex[4346:60b] 添加了第 9 块

2014-04-08 14:43:16.491 dispex[4346:60b] 块 9

2014-04-08 14:43:16.492 dispex[4346:60b] 块 10 添加

2014-04-08 14:43:16.492 dispex[4346:60b] 块 10

2014-04-08 14:43:16.492 dispex[4346:60b] 所有块都添加到队列中 --> 函数返回

最后,这里我们使用了dispatch_sync with 并发队列。它看起来完全等于同步/串行对。在这种情况下就是这样。这种行为的原因是,如果队列是并发的,它没有其他块要执行,因为我们正在使用同步调度程序,因此它会等待添加下一个块,直到实际执行完毕为止。这种类型的情侣(同步/并发) 如果我们也添加到队列中,则很有用,块dispatch_async。在这种情况下,调度程序可以将其他块添加到要执行的队列中。

希望这个迷你演示有用;)

Cheers!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当同步/异步与串行/并发队列混合时,调度程序如何工作? 的相关文章

  • SwiftUI - 从 NSObject 继承的 ObservableObject 在 iOS 13 中不会更新

    我知道 这是 无法在 iOS XX 中工作 问题之一 但我完全陷入困境 所以我有一个ObservableObject继承自的类NSObject 因为我需要听委托方法UISearchResultsUpdating class SearchBa
  • 禁用 iPhone 4S / 新 iPad 键盘上的听写按钮

    我们的应用程序是一个医疗保健应用程序 我们的应用程序中有一个符合 HIPAA 标准的语音识别器 所有听写都可以通过它进行 医院不希望医生意外开始与不符合 HIPAA 标准的 Nuance Dragon 服务器进行对话 因此 我正在寻找可以抑
  • 是否可以在增强现实应用程序中使用自定义 iOS UI 元素(例如 UILabel)

    我想知道是否可以使用像这样的 UI 元素UIButton UILabel在带有 ARKit 的增强现实应用程序中 如果您也对 UIView 子类的透明度模式感兴趣 请尝试我的示例https github com erikhric ar me
  • 防止点击 MKAnnotation 时检测到 MKMapView 上的触摸事件

    我有一个 UITapGestureRecognizer 当用户点击地图时 它将在我的 MKMap 上隐藏和显示工具栏 简单 但是 当用户点击 MKMapAnnotation 时 我不希望地图以正常方式响应点击 如上所述 此外 当用户点击地图
  • 奇怪的父/子NSManagedObjectContext现象

    我创建了两个这样的上下文 create writer MOC privateWriterContext NSManagedObjectContext alloc initWithConcurrencyType NSPrivateQueueC
  • AppDelegate 的变量用作全局变量不起作用

    我想使用我的 AppDelegate 来存储任何其他类都可以访问的对象 我已经像这样声明了这个 AppDelegate interface MyAppDelegate UIResponder
  • malloc:***错误:已释放对象的校验和不正确 - 对象可能在释放后被修改

    我的 iOS 应用程序有一个大问题 它有时会崩溃 而没有详细的调试错误 堆栈跟踪为空 这是堆栈跟踪中仅有的两行 UIApplicationMain 中的 符号存根 UIHostedTextServiceSession DismissText
  • AFNetworking 上传图片

    我看过一些例子 但我认为我的问题可能出在 PHP 中 我正在尝试使用 AFNetworking 将图像从 iPhone 上传到服务器 这是我的 obj c 代码 IBAction uploadButtonClicked id sender
  • 如何将 UIImageView 裁剪为自定义形状

    用户是否可以在该位周围画一条虚线 圆圈 UIImageView他们希望裁剪到 然后为UIImageView调整大小到这些点 这有点像 Photoshop 中的套索 选取框效果 更新 从 iOS 8 x 开始 UIImageView 提供了m
  • 无需 iPhone 6 Plus 即可预览 iOS 应用程序

    我已经在 Yosemite 中使用 iPhone 6 和 Quicktime 完成了 iOS 应用程序预览 视频 但我无法在 iTunes Connect 中为 iPhone 6 上传它 而且我没有 iPhone 6 设备 有没有办法在没有
  • ShareKit + Facebook 身份验证不起作用

    我正在使用 ShareKit 从我正在开发的 PhoneGap 应用程序发布到 Facebook 我在 Facebook 中创建了该应用程序 并在我的项目中安装了该插件 Twitter 工作正常 但当我尝试在 Facebook 上分享时出现
  • iOS 设置 MKMapView 中心,因此提供的位置位于底部中心

    我有一个 MKMapView 和一个永不改变的 CLLocationCooperative2D 我想做的是将地图居中 以便该坐标将放置在地图的底部中心 我可以用简单的方法将地图集中在这个坐标上 MKCoordinateRegion view
  • 如何修复 ReactiveCocoa(带有 CocoaPods)的安装?

    这里是新手 尝试将 ReactiveCocoa 2 2 4 和 CocoaPods 安装到项目中 但在运行时遇到错误 我用过github 上的这个 podspec https github com CocoaPods Specs blob
  • UICollectionReusableView 方法未被调用

    我希望我的部分位于UICollectionView有一个带有图像的标题 我已按照以下步骤操作 在故事板中 分配了一个标题作为我的附件UICollectionView 给它一个标识符 创建了一个子类UICollectionReusableVi
  • NSDateFormatter:根据 currentLocale 的日期,不包含年份

    这不会太难吧 我想显示不带年份的日期 例如 8 月 2 日 美国 或 02 08 德国 它也必须适用于许多其他语言环境 到目前为止 我唯一的想法是对年份进行正常格式 然后从生成的字符串中删除年份部分 我认为你需要看一下 NSString d
  • 使用prepareForSegue传递数据

    我试图将数据从viewController 1传递到viewController2 我有2个按钮和1个segue 因此有一个segue标识符 这2个按钮 按下时每个按钮应显示 1个标签用于显示标题 1个textView用于显示定义 我很难显
  • 所有针对 iTunes Connect 的构建,导入此构建时出错 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我将构建上传到应用程序商店 之后它在活动中显示错误 任何人都可以帮帮我 SOLVED 转到构建设置 gt 搜索 bitcode gt 转启
  • iOS 使用 NSColor 与 UIColor?

    有什么区别UIColor and NSColor 什么时候会使用每一种 我碰到NSColor在试图弄清楚的同时UIColor用于 iOS 中的属性字符串 我理解使用UIColor对于 UIKit 等 但我不认为NSColor对于这种事情确实
  • 使用 nib 作为带有 nib 类的表节标题

    我想创建一个加载 nib 文件并将其设置为标题 UIView 的节标题 这个 nib 文件还将有一个关联的类 其中插座和操作连接到 因此我想像平常一样使用 nib 加载该类 我在网上搜索并找到了几个类似的答案 但我找不到任何适合我的答案 经
  • 选择 UITableViewCell 时 UIView 背景颜色消失

    我在界面生成器中构建了一个简单的 tableViewCell 它包含一个包含图像的 UIView 现在 当我选择单元格时 会显示默认的蓝色选择背景 但 UIView 的背景颜色消失了 我的 UITableViewCell 的实现文件没有做任

随机推荐