首页 > 其他分享 >理解dispatch_async

理解dispatch_async

时间:2024-06-11 15:31:53浏览次数:16  
标签:name thread number dispatch 2nd 理解 async main

在这里插入图片描述

Submits a block for asynchronous execution on a dispatch queue and returns immediately.
提交一个块以在调度队列上异步执行并立即返回

code showing

  • 以一个最简单的demo开始
// 创建一个同步队列
dispatch_queue_t syncQueue = dispatch_queue_create("io.sqi.MySyncQueue", DISPATCH_QUEUE_SERIAL);
NSLog(@"0️⃣ zero, current thread: %@", [NSThread currentThread]);
// 使用 dispatch_async 在 syncQueue 上异步执行
dispatch_async(syncQueue, ^{
NSLog(@"2️⃣ 2nd, current thread: %@", [NSThread currentThread]);
});
NSLog(@"1️⃣ 1st, current thread: %@", [NSThread currentThread]);

在主线程上执行以上代码, 运行结果如下:

0️⃣ zero, <_NSMainThread: 0x60000170c000>{number = 1, name = main}
1️⃣ 1st, <_NSMainThread: 0x60000170c000>{number = 1, name = main}
2️⃣ 2nd, <NSThread: 0x6000017427c0>{number = 7, name = (null)}

可以看到,为了异步执行 block, 系统开辟了一条 number = 7 的新线程


  • 加入同步执行任务
// 创建一个同步队列
dispatch_queue_t syncQueue = dispatch_queue_create("io.sqi.MySyncQueue", DISPATCH_QUEUE_SERIAL);
NSLog(@"0️⃣ zero, current thread: %@", [NSThread currentThread]);
// 使用 dispatch_async 在 syncQueue 上异步执行
dispatch_async(syncQueue, ^{
NSLog(@"1️⃣ 1st, current thread: %@", [NSThread currentThread]);
});
// 使用 dispatch_sync 在 syncQueue 上同步执行
dispatch_sync(syncQueue, ^{
NSLog(@"2️⃣ 2nd, current thread: %@", [NSThread currentThread]);
});
NSLog(@"3️⃣ 3rd, current thread: %@", [NSThread currentThread]);

在主线程上执行以上代码, 运行结果如下:

0️⃣ zero, <_NSMainThread: 0x6000017080c0>{number = 1, name = main}
1️⃣ 1st, <NSThread: 0x60000171c940>{number = 5, name = (null)}
2️⃣ 2nd, <_NSMainThread: 0x6000017080c0>{number = 1, name = main}
3️⃣ 3rd, <_NSMainThread: 0x6000017080c0>{number = 1, name = main}

因为2nd需要同步执行,所以 2nd 的执行要在 3rd 前面,因为1st是先加入 syncQueue, 所以 1st 的执行要在 2nd 前面


  • 变更为并发队列
dispatch_queue_t concurrentQueue = dispatch_queue_create("io.sqi.MyConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"0️⃣ zero, current thread: %@", [NSThread currentThread]);
// 使用 dispatch_async 在 concurrentQueue 上异步执行
dispatch_async(concurrentQueue, ^{
NSLog(@"1️⃣ 1st, current thread: %@", [NSThread currentThread]);
});
// 使用 dispatch_sync 在 concurrentQueue 上同步执行
dispatch_sync(concurrentQueue, ^{
NSLog(@"2️⃣ 2nd, current thread: %@", [NSThread currentThread]);
});
NSLog(@"3️⃣ 3rd, current thread: %@", [NSThread currentThread]);

同样在 main thread 上执行,运行结果如下:

// 情况一
0️⃣ zero, <_NSMainThread: 0x600001708000>{number = 1, name = main}
2️⃣ 2nd, <_NSMainThread: 0x600001708000>{number = 1, name = main}
1️⃣ 1st, <NSThread: 0x6000017537c0>{number = 5, name = (null)}
3️⃣ 3rd, <_NSMainThread: 0x600001708000>{number = 1, name = main}
// 情况二
0️⃣ zero, <_NSMainThread: 0x600001708000>{number = 1, name = main}
2️⃣ 2nd, <_NSMainThread: 0x600001708000>{number = 1, name = main}
3️⃣ 3rd, <_NSMainThread: 0x600001708000>{number = 1, name = main}
1️⃣ 1st, <NSThread: 0x6000017537c0>{number = 5, name = (null)}
  1. 因为是并发队列,1st 无需等待 2nd 执行完毕才开始,可以同时执行;
  2. dispatch_sync 不具备开启新线程的能力,所以依旧需要在 main thread 上执行;
  3. 为什么 2nd 总是在 3rd 的前面 ?

    分析如下:首先 dispatch_async 将任务放入队列中后立即返回,不阻塞当前线程,所以 2nd 总是会立即执行,而 dispatch_async 提交的队列的 block 需要开辟新的线程以执行 block 中的任务,这是一个耗时操作;

标签:name,thread,number,dispatch,2nd,理解,async,main
From: https://blog.csdn.net/qfeung/article/details/139594740

相关文章

  • 我所理解的机器学习
    (2017年写的博客,搬过来)断断续续看了几个月的机器学习,我觉得是时候总结一下了。正如题目讲的那样,我只说我所理解的机器学习,我不能保证我理解的都对,很多东西可能是我的误解,但无论说错了什么,我都认。如果有人发现错误,恳请指正,不胜感激。我不讲算法也不讲公式推导,因为,我从头到尾都......
  • 深入理解C++中的常量和宏:const、#define、typedef和inline详解
    一、const 与 #define 的区别1.定义方式和类型const 定义的常量是有类型的变量。#define 只是文本替换,不带类型。constintMAX_VALUE=100;//MAX_VALUE是一个整数类型的常量#defineMAX_VALUE100//MAX_VALUE是一个文本替换,它不关联任何类型2.生效......
  • 理解均线指标
    交易者分两种,一种是在趋势还没出现的时候下单,另一种是跟随已经出现了趋势的人。这两种人都是靠趋势策略来赚钱的,区别是第一种人会分析指标,判断趋势是否出现,第二种人只是跟单的人,没有脑子的赚小钱。关于一个品种的价格,是按照供给和需求来给定的。 价格越高,供给的量就会越大,需......
  • 白话理解和使用DOCKER VOLUME
    Docker使用Volume来管理宿主机和容器内数据的映射  什么是数据卷(Volume)Docker镜像被存储在一系列的只读层中。当我们创建一个容器时,Docker会读取镜像(只读),并在其顶部添加一层读写层。如果正在运行中的容器修改了现有文件,该文件将会被拷贝出底层的只读层,放到最顶层的读写层中......
  • pydispatch:Python中的事件驱动编程
    pydispatch是一个轻量级的事件调度器,广泛应用于实现观察者模式。它允许对象之间通过事件进行通信,而无需直接引用彼此,从而实现代码的模块化和可维护性。1.安装pydispatch使用pip安装pydispatch库:pipinstallpydispatch 2.基本概念pydispatch库中有3个核心概念:信号(Sig......
  • yolov5模型评估指标R、P、map50怎么理解?
    R(Recall,召回率)定义:召回率是所有真实正样本中被模型正确预测为正样本的比例。计算公式:R=TP/(TP+FN),其中TP表示真正例(TruePositives),即被模型正确预测为正样本的实例;FN表示假反例(FalseNegatives),即被模型错误预测为负样本的实例。解释:召回率衡量了模型对正样本的查......
  • 优雅的快排之分治与递归思想,透彻理解快排
    摘要:给你一个数组,要求你对其按照从小到大的顺序进行排序.你是怎么做的呢?英国计算机科学家东尼.霍尔在英国国家物理实验室工作的时候提出一种名为快速排序的排序算法,它可以高效地将一个数组进行快速排序.那么霍尔是怎么想到的?接下来根据从y总那里学到的以及个人的理解来介......
  • 深入理解 C++ 动态内存管理:new vs malloc
    概述new/delete 是C++的关键字,需要编译器支持。malloc/free 是库函数,需要头文件支持。使用 new 申请内存分配时无需指定内存块大小,编译器会自动计算。而 malloc 需要明确指定所需内存的大小。new 会返回对象类型的指针,类型安全。而 malloc 返回 void*,需要进行强制......
  • 对#include <stdio.h>的简单理解
    stdio.h是C语言中的一个文件,文件名是stdio,拓展名是.h,就像.exe和.jpg一样。当然.h是C语言的文件类型。stdio原意是standardinput&output,是标准输入和输出。标准输入函数是printf(),标准输出函数是scanf(),如果你写的程序中用到了这两个函数,就需要#include<stdio.h>,没用到则......
  • 【Docker系列】跨平台 Docker 镜像构建:深入理解`--platform`参数
    ......