(五十五)iOS多线程之GCD

GCD的全称为Grand Central Dispatch,翻译为大中央调度,是Apple开发的一个多线程编程解决方法。


进程和线程的概念:

正在进行中的程序被称为进程,负责程序运行的内存分配,每一个进程都有自己独立的虚拟内存空间。

线程是进程中一个独立的执行路径,即主线程,主线程有1M的栈区,对于耗时的执行路径,可以放在子线程(512K栈区)中执行。

Tip:新建线程会消耗内存空间和CPU事件,线程太多会降低系统的运行性能,多线程是通过CPU时分复用实现的。

Tip:多线程是为了并发执行多项任务,不会提高单个算法本身的执行效率。


iOS中三种多线程技术:

1.NSThread

建立一个线程方便,但是管理多个线程非常困难,但是NSThread的currentThread方法可以跟踪任务所在的线程。

2.GCD Grand Central Dispatch(基于C语言的底层API),使用block来定义任务,推荐使用。

3.NSOperation/NSOperationQueue 使用GCD的一套OC API,提供了一些GCD中不易实现的特性。

Tip:直接使用GCD更好一些。


GCD的核心思想是把操作(block定义任务)放入队列中,队列的特点是FIFO(先进先出),出队时操作被分配到CPU上进行处理。

Tip:队列不是线程,也不表示对应的CPU,例如双核CPU,谁空闲分配给谁,出队时分配到哪个CPU是不需要被关心的。

Tip:GCD的函数都是以dispatch开头的,dispatch的含义是分派、调度。

Tip:NSThread的currentThread得到的是name和num字典,其中num=1表示主线程。

【进程同步和异步的概念】

进程同步:一个操作没有完成则不返回,必须一件一件的做事情,一件事情返回了才能做下一件事情。

进程异步:多个操作交替进行,操作的返回时机不确定。

【串、并行队列】

Tip:同步为sync,异步为async

1.串行队列的异步任务:使用一个子线程依次执行。

应用:串行队列中的异步任务会依次执行,例如先下载图片,然后处理,两个任务有明确的先后顺序,顺序是确定的。

/***  串行队列*/
- (void)gcdDemo1{dispatch_queue_t q = dispatch_queue_create("queue<1>", DISPATCH_QUEUE_SERIAL);for (int i = 0; i < 3; i++) {dispatch_async(q, ^{NSLog(@"%@ i = %d",[NSThread currentThread],i); //跟踪当前线程});}
}
打印串行队列的输出发现,i的值是从0到2分别输出的:

2015-02-16 17:28:11.559 多线程初步[1493:119215] <NSThread: 0x7986cbb0>{number = 2, name = (null)} i = 0
2015-02-16 17:28:11.559 多线程初步[1493:119215] <NSThread: 0x7986cbb0>{number = 2, name = (null)} i = 1
2015-02-16 17:28:11.559 多线程初步[1493:119215] <NSThread: 0x7986cbb0>{number = 2, name = (null)} i = 2

2.并行队列的异步任务:使用多个子线程无序执行,一般任务较少时几个任务就开几个线程,较多时则开部分线程。

应用:一系列的异步任务没有先后顺序。

/***  并行队列*/
- (void)gcdDemo2{dispatch_queue_t q = dispatch_queue_create("queue<2>", DISPATCH_QUEUE_CONCURRENT);for (int i = 0; i < 3; i++) {dispatch_async(q, ^{NSLog(@"%@ i = %d",[NSThread currentThread],i); //跟踪当前线程});}}
打印输出,发现i的值是随机排列的:

2015-02-16 17:28:55.084 多线程初步[1521:119972] <NSThread: 0x796347d0>{number = 2, name = (null)} i = 2
2015-02-16 17:28:55.084 多线程初步[1521:119975] <NSThread: 0x79956380>{number = 3, name = (null)} i = 0
2015-02-16 17:28:55.084 多线程初步[1521:119973] <NSThread: 0x796a2ba0>{number = 4, name = (null)} i = 1

3.串行队列的同步任务:只使用主线程顺序执行,用处较少。

/***  串行队列的同步任务*/
- (void)gcdDemo12{dispatch_queue_t q = dispatch_queue_create("queue<1>", DISPATCH_QUEUE_SERIAL);for (int i = 0; i < 3; i++) {dispatch_sync(q, ^{NSLog(@"%@ i = %d",[NSThread currentThread],i); //跟踪当前线程});}
}
2015-02-16 17:33:12.938 多线程初步[1574:121669] <NSThread: 0x7a25f5a0>{number = 1, name = main} i = 0
2015-02-16 17:33:12.938 多线程初步[1574:121669] <NSThread: 0x7a25f5a0>{number = 1, name = main} i = 1
2015-02-16 17:33:12.938 多线程初步[1574:121669] <NSThread: 0x7a25f5a0>{number = 1, name = main} i = 2

4. 并行队列的同步任务:只使用主线程依次执行。

Tip:串行队列异步任务的用处是最大的,既可以异步,又可以顺序执行

Tip:如果先向队列中加入异步任务,再加入同步任务,同步任务会穿插在异步任务中运行。

Tip:并行队列难以控制执行顺序与最大并发数,容易出错。


5.线程名字的作用:打了断点后,可以在左侧看到线程名称。

Tip:通过点击CPU的运行状态还可以得到每个线程的CPU占用情况。


6.非ARC开发时,不要忘记写dispatch_release(q);

【全局队列】

Apple提供的,供所有App共同使用,它是一种特殊的并行队列

使用dispatch_get_global_queue获取,第一个参数为优先级,通过右侧的提示输入即可,第二个是供以后使用的,传入0即可。

与并行队列的区别:不需要创建,名称以com.apple开头。

缺点:调试时无法得到准确队列的名称。

【主线程队列】

注意:iOS只能在主线程上更新UI,因此与UI更新有关的操作应该在主线程执行,它是一种特殊的串行队列

使用dispatch_get_main_queue()函数获取。

与串行队列的区别:不需要创建,名称以com.apple开头。

【进程阻塞】

注意主线程是一直工作的,除非将程序杀掉,否则主线程的工作永远不会结束。

由于同步任务要等待前面的任务,因此在主线程中加入同步任务,会引起进程阻塞。

Tip:主线程中只能添加异步任务

【小结】

1.并发编程对多线程编程进行了封装,不需要关心线程的创建与回收,是为了让程序员从复杂的线程控制中解脱出来,只需要面对队列和任务即可。

2.注意队列的优先级永远写DISPATCH_QUEUE_PRIORITY_DEFAULT,优先级出错时会造成优先级反转,低优先级的线程可能会阻塞高优先级的线程,为了保险起见,应该使用串行队列的异步任务。

3.同步任务嵌套同步任务,会引发阻塞,原因在于,第一个任务执行完毕的条件是第二个任务执行完毕,而第二个任务执行完毕的条件是第一个任务执行完毕,因此二者相互等待,无法结束。

4.GCD队列有5个优先级,优先级从高到底分别为Main->High->Default->Low->Background,后面四级都放入GCD线程池中,最高级的即为主线程。

转载于:https://www.cnblogs.com/aiwz/p/6154195.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/420200.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql优化varchar索引_MySQL优化--概述以及索引优化分析

一、MySQL概述1.1、MySQL文件含义通过如下命令查看show variables like %dir%;MySQL文件位置及含义名称值备注basedir/usr/安装路径character_sets_dir/usr/share/mysql-8.0/charsets/保存字符集目录datadir/var/lib/mysql/数据存放路径lc_messages_dir/usr/share/mysql-8.0/pl…

atitit.orm的缺点与orm框架市场占有率,选型attilax总结

atitit.orm的缺点与orm框架市场占有率&#xff0c;选型attilax总结 1. attilax的orm框架要求 1 2. orm框架市场占有率 2 3. spring jdbc templt 3 4. eclipselink /toplink 不好用 4 5. jooq 的总结 4 6. attilax的选择 atiorm 4 7. 参考 4 1. attilax的orm框架要求 1.无需配置…

前端学习(1366):express入门

const express require(express);const app express(); app.get(/, (req, res) > {//send 响应内容的累心//http 状态码res.send(hello geyao); }) app.get(/list, (req, res) > {//send 响应内容的累心//http 状态码res.send({ name: 张三, age: 20 }); }) app.listen…

python中参数传递_python中参数传递

在编程语言中&#xff0c;函数的参数传递有两种情况&#xff1a;按值类型传递num 10def double(arg):argarg*2print(arg)double(num)调用该函数&#xff0c;传入一个变量&#xff0c;其实传入的是该变量的一个副本&#xff0c;该变量在函数中发生变化&#xff0c;不影响函数外…

Hybrid框架UI重构之路:五、前端那点事儿(HTML、CSS)

上文回顾 &#xff1a;Hybird框架UI重构之路&#xff1a;四、分而治之 这里讲述在开发的过程中&#xff0c;一些HTML、CSS的关键点。 单页模式的页面结构在单页模式中&#xff0c;弱化HTML的概念&#xff0c;把HTML当成一个容器&#xff0c;BODY中显示的主体内容才是页面&#…

前端学习(1367):什么是中间件

const express require(express);const app express(); app.get(/request, (req, res, next) > {//send 响应内容的累心//http 状态码req.name 张三;next(); }) app.get(/request, (req, res) > {//send 响应内容的累心//http 状态码res.send(req.name); }) app.liste…

python choose语句作用_理解闭包是如何与变量作用域相互影响的

原文标题&#xff1a;KNOW HOW CLOSURES INTERACT WITH VARIABLE SCOPE比如说你现在想要对一组数字进行排序&#xff0c;同时希望提高一组数字的优先级使这组数字优先显示。这种模式在展示用户接口时非常有用&#xff0c;在展示用户接口时经常需要优先展示一些重要信息以及异常…

前端学习(1368):app.use使用

const express require(express);const app express(); app.use((req, res, next) > {console.log(请求走了use中间件);next(); }) app.use(/request, (req, res, next) > {console.log(请求走了use中间件/hh)next() }) app.get(/list, (req, res) > {//send 响应内…

JDE Client开发端 左侧边栏设置

转载于:https://www.cnblogs.com/GYoungBean/p/4299317.html

cmd oracle 连接实例_C#连接Oracle数据库的实例方法

1.建立连接字符串&#xff0c;里面包含数据库名称、用户名和密码2.建立操作字符串&#xff0c;里面是对数据操作的SQL语句3.建立Connection&#xff0c;用连接字符串作为参数建立4.建立Command&#xff0c;用操作字符串和Connection作为参数5.建立DataAdapter&#xff0c;用Com…

59-混沌操作法感悟2.(2015.2.25)

混沌操作法感悟2羊年到了&#xff0c;今年要好好努力&#xff0c;争取赚到满意的收入。今天刚来到上海&#xff0c;明天开始上班&#xff0c;今天更新下春节期间在家的思考。随机性被视为噪音是因为时间因素&#xff0c;时间框架的长短性。如果以小时为时间框架&#xff0c;这种…

insert事务隔离mysql_MySQL数据库详解(三)MySQL的事务隔离剖析

提到事务&#xff0c;你肯定不陌生&#xff0c;和数据库打交道的时候&#xff0c;我们总是会用到事务。最经典的例子就是转账&#xff0c;你要给朋友小王转 100 块钱&#xff0c;而此时你的银行卡只有 100 块钱。转账过程具体到程序里会有一系列的操作&#xff0c;比如查询余额…

前端学习(1369):中间件应用

const express require(express);const app express(); app.use((req, res, next) {res.send(网站维护中); }) app.use(/admin, (req, res, next) > {let isLogin false;if (isLogin) {next()} else {res.send(你还没有登录);} }) app.get(/admin, (req, res) > {res.…

宽容与忍耐 忍乃济——这是《尚书》这部中国令世人刮目的奇书告诉我们的真理 保身第一法:谦逊;处事第一法:安详;待人第一法:涵容(宽容);养心第一法:洒脱...

宽容与忍耐 不让古人&#xff0c;是谓有志&#xff1b;不让今人&#xff0c;是谓无量。 忍耐若与敏感、魄力、思维、迅速行动结合&#xff0c;将所向无敌。 脾气服从理性的判断才会成功&#xff0c;否则只是动物式愤怒欲的满足&#xff0e;或从心理学的角度讲是怒需求。 大智者…

mysql数据表交叉引用_数据定义语句

数据定义语句MySQL 8.0支持原子数据定义语言(DDL)语句。此功能称为原子DDL。原子DDL语句将数据字典更新&#xff0c;存储引擎操作和与DDL操作相关联的二进制日志写入操作组合到单个原子事务中。即使事务在操作期间停止&#xff0c;事务也可以提交&#xff0c;并在数据字典&…

前端学习(1370):错误处理中间件

const express require(express);const app express(); app.get(/index, (req, res) > {throw new Error(程序发生了错误);/* res.send(); */ }) app.use((err, req, res, next) > {res.status(500).send(err.message); }) app.listen(3000); console.log(服务器启动成…

MySQL官方备份_Mysqlbackup 备份详解(mysql官方备份工具)

A.1全库备份.命令:mysqlbackup--defaults-file/home/mysql-server/mysql3/my.cnf --userroot --passwordroot --databases"mysql total2" --with-timestamp --backup-dir/home/mysql-server/backup backup参数说明&#xff1a;--defaults-filemy.cnf文件的路径…

Linux下的库文件搜索路径

对于以压缩包发布的软件&#xff0c;在它的目录下通常都有一个配置脚本configure&#xff0c;它的作用确定编译参数(比如头文件位置、连接库位置等)&#xff0c;然后生成Makefile以编译程序。可以进入该软件的目录&#xff0c;执行"./configure --help"命令查看使用帮…

慕课笔记 mysql读写分离_mysql读写分离笔记

主数据库执行命令&#xff1a;show master status;得到结果mysql-bin.0000092123从数据库执行命令stop slave;change master tomaster_host47.95.247.135,master_port3306,master_userroot,master_passwordroot,master_log_filemysql-bin.000009,master_log_pos4353;start slav…

ruby记录

ruby记录 --posted on 2015-02-28 20:52 zlingh 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblogs.com/zlingh/p/4306195.html