- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章iOS 多线程总结之GCD的使用详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
进程与线程 。
进程就是一个应用程序在处理机上的一次执行过程,它是一个动态的概念,而线程是进程中的一部分,进程包含多个线程在运行.
线程是指进程内的一个执行单元,也是进程内的可调度实体. 。
与进程的区别
(1)地址空间:线程是进程内的一个执行单元;进程至少有一个线程;它们共享进程的地址空间;而进程有自己独立的地址空间; (2)资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源 (3)线程是处理器调度的基本单位,但进程不是. (4)二者均可并发执行. 。
GCD 。
1.什么是GCD?
全称是Grand Central Dispatch,可译为“伟大的中枢调度器” 。
纯C语言,提供了非常多强大的函数 。
2.GCD的优势 。
GCD是苹果公司为多核的并行运算提出的解决方案 。
GCD会自动利用更多的CPU内核(比如双核、四核) 。
GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程) 。
程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码 。
队列与任务 。
1.队列主要包含三种:主线程队列、并行队列、串行队列 。
2.任务主要包含两种:异步任务和同步任务 。
多线程执行过程就是把任务放在队列中去执行的过程 。
(在计算机操作系统中对异步和同步有很深入的概念和定义,并影响到计算机系统有单线程到多线程的过渡发展,其中牵涉到线程切换、时间片等概念。但在GCD这里我们只做大致使用区别) 。
队列:
任务
同步(sync) 和 异步(async) 的主要区别在于会不会阻塞当前线程,直到 Block 中的任务执行完毕! 。
如果是 同步(sync) 操作,它会阻塞当前线程并等待 Block 中的任务执行完毕,然后当前线程才会继续往下运行.
如果是 异步(async)操作,当前线程会直接往下执行,它不会阻塞当前线程.
3.队列的创建方法 。
可以使用dispatch_queue_create来创建对象,需要传入两个参数,第一个参数表示队列的唯一标识符,用于DEBUG,可为空;第二个参数用来识别是串行队列还是并行队列。DISPATCH_QUEUE_SERIAL表示串行队列,DISPATCH_QUEUE_CONCURRENT表示并行队列.
1
2
3
4
|
// 串行队列的创建方法
dispatch_queue_t queue= dispatch_queue_create(
"test.queue"
, DISPATCH_QUEUE_SERIAL);
// 并行队列的创建方法
dispatch_queue_t queue= dispatch_queue_create(
"test.queue"
, DISPATCH_QUEUE_CONCURRENT);
|
对于并行队列,还可以使用dispatch_get_global_queue来创建全局并行队列。GCD默认提供了全局的并行队列,需要传入两个参数。第一个参数表示队列优先级,一般用DISPATCH_QUEUE_PRIORITY_DEFAULT。第二个参数暂时没用,用0即可.
4.任务的创建方法 。
1
2
3
4
5
6
7
8
|
// 同步执行任务创建方法
dispatch_sync(queue, ^{
NSLog(@
"%@"
,[NSThread currentThread]);
// 这里放任务代码
});
// 异步执行任务创建方法
dispatch_async(queue, ^{
NSLog(@
"%@"
,[NSThread currentThread]);
// 这里放任务代码
});
|
虽然使用GCD只需两步,但是既然我们有两种队列,两种任务执行方式,那么我们就有了四种不同的组合方式。这四种不同的组合方式是 。
1.并行队列 + 同步执行 2.并行队列 + 异步执行 3.串行队列 + 同步执行 4.串行队列 + 异步执行 。
5.GCD的基本使用 。
并行队列+同步执行 。
不会开启新线程,执行完一个任务,再执行下一个任务 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
-(
void
) syncConcurrent{
NSLog(@
"syncConcurrent---begin"
);
dispatch_queue_t queue= dispatch_queue_create(
"test.queue"
, DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
for
(
int
i = 0; i < 2; ++i) {
NSLog(@
"1------%@"
,[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for
(
int
i = 0; i < 2; ++i) {
NSLog(@
"2------%@"
,[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for
(
int
i = 0; i < 2; ++i) {
NSLog(@
"3------%@"
,[NSThread currentThread]);
}
});
NSLog(@
"syncConcurrent---end"
);
}
|
并行队列 + 异步执行 。
可同时开启多线程,任务交替执行 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
- (
void
) asyncConcurrent
{
NSLog(@
"asyncConcurrent---begin"
);
dispatch_queue_t queue= dispatch_queue_create(
"test.queue"
, DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
for
(
int
i = 0; i < 2; ++i) {
NSLog(@
"1------%@"
,[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for
(
int
i = 0; i < 2; ++i) {
NSLog(@
"2------%@"
,[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for
(
int
i = 0; i < 2; ++i) {
NSLog(@
"3------%@"
,[NSThread currentThread]);
}
});
NSLog(@
"asyncConcurrent---end"
);
}
|
串行队列 + 同步执行 。
不会开启新线程,在当前线程执行任务。任务是串行的,执行完一个任务,再执行下一个任务 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
- (
void
) syncSerial
{
NSLog(@
"syncSerial---begin"
);
dispatch_queue_t queue = dispatch_queue_create(
"test.queue"
, DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
for
(
int
i = 0; i < 2; ++i) {
NSLog(@
"1------%@"
,[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for
(
int
i = 0; i < 2; ++i) {
NSLog(@
"2------%@"
,[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for
(
int
i = 0; i < 2; ++i) {
NSLog(@
"3------%@"
,[NSThread currentThread]);
}
});
NSLog(@
"syncSerial---end"
);
}
|
串行队列 + 异步执行 。
会开启新线程,但是因为任务是串行的,执行完一个任务,再执行下一个任务 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
- (
void
) asyncSerial
{
NSLog(@
"asyncSerial---begin"
);
dispatch_queue_t queue = dispatch_queue_create(
"test.queue"
, DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
for
(
int
i = 0; i < 2; ++i) {
NSLog(@
"1------%@"
,[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for
(
int
i = 0; i < 2; ++i) {
NSLog(@
"2------%@"
,[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for
(
int
i = 0; i < 2; ++i) {
NSLog(@
"3------%@"
,[NSThread currentThread]);
}
});
NSLog(@
"asyncSerial---end"
);
}
|
主队列 + 同步执行 。
互等卡住不可行(在主线程中调用),会出现死锁 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
- (
void
)syncMain
{
NSLog(@
"syncMain---begin"
);
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
for
(
int
i = 0; i < 2; ++i) {
NSLog(@
"1------%@"
,[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for
(
int
i = 0; i < 2; ++i) {
NSLog(@
"2------%@"
,[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for
(
int
i = 0; i < 2; ++i) {
NSLog(@
"3------%@"
,[NSThread currentThread]);
}
});
NSLog(@
"syncMain---end"
);
}
|
这是因为我们在主线程中执行这段代码。我们把任务放到了主队列中,也就是放到了主线程的队列中。而同步执行有个特点,就是对于任务是立马执行的。那么当我们把第一个任务放进主队列中,它就会立马执行。但是主线程现在正在处理syncMain方法,所以任务需要等syncMain执行完才能执行。而syncMain执行到第一个任务的时候,又要等第一个任务执行完才能往下执行第二个和第三个任务.
那么,现在的情况就是syncMain方法和第一个任务都在等对方执行完毕。这样大家互相等待,所以就卡住了,所以我们的任务执行不了.
主队列 + 异步执行 。
只在主线程中执行任务,执行完一个任务,再执行下一个任务 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
- (
void
)asyncMain
{
NSLog(@
"asyncMain---begin"
);
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
for
(
int
i = 0; i < 2; ++i) {
NSLog(@
"1------%@"
,[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for
(
int
i = 0; i < 2; ++i) {
NSLog(@
"2------%@"
,[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for
(
int
i = 0; i < 2; ++i) {
NSLog(@
"3------%@"
,[NSThread currentThread]);
}
});
NSLog(@
"asyncMain---end"
);
}
|
GCD的队列组 dispatch_group 。
有时候我们会有这样的需求:分别异步执行2个耗时操作,然后当2个耗时操作都执行完毕后再回到主线程执行操作。这时候我们可以用到GCD的队列组.
我们可以先把任务放到队列中,然后将队列放入队列组中.
调用队列组的dispatch_group_notify回到主线程执行操作.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 执行1个耗时的异步操作
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 执行1个耗时的异步操作
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 等前面的异步操作都执行完毕后,回到主线程...
});
|
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.
原文链接:http://www.jianshu.com/p/cb5593cb11f1?utm_source=tuicool&utm_medium=referral 。
最后此篇关于iOS 多线程总结之GCD的使用详解的文章就讲到这里了,如果你想了解更多关于iOS 多线程总结之GCD的使用详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我在网上搜索但没有找到任何合适的文章解释如何使用 javascript 使用 WCF 服务,尤其是 WebScriptEndpoint。 任何人都可以对此给出任何指导吗? 谢谢 最佳答案 这是一篇关于
我正在编写一个将运行 Linux 命令的 C 程序,例如: cat/etc/passwd | grep 列表 |剪切-c 1-5 我没有任何结果 *这里 parent 等待第一个 child (chi
所以我正在尝试处理文件上传,然后将该文件作为二进制文件存储到数据库中。在我存储它之后,我尝试在给定的 URL 上提供文件。我似乎找不到适合这里的方法。我需要使用数据库,因为我使用 Google 应用引
我正在尝试制作一个宏,将下面的公式添加到单元格中,然后将其拖到整个列中并在 H 列中复制相同的公式 我想在 F 和 H 列中输入公式的数据 Range("F1").formula = "=IF(ISE
问题类似于this one ,但我想使用 OperatorPrecedenceParser 解析带有函数应用程序的表达式在 FParsec . 这是我的 AST: type Expression =
我想通过使用 sequelize 和 node.js 将这个查询更改为代码取决于在哪里 select COUNT(gender) as genderCount from customers where
我正在使用GNU bash,版本5.0.3(1)-发行版(x86_64-pc-linux-gnu),我想知道为什么简单的赋值语句会出现语法错误: #/bin/bash var1=/tmp
这里,为什么我的代码在 IE 中不起作用。我的代码适用于所有浏览器。没有问题。但是当我在 IE 上运行我的项目时,它发现错误。 而且我的 jquery 类和 insertadjacentHTMl 也不
我正在尝试更改标签的innerHTML。我无权访问该表单,因此无法编辑 HTML。标签具有的唯一标识符是“for”属性。 这是输入和标签的结构:
我有一个页面,我可以在其中返回用户帖子,可以使用一些 jquery 代码对这些帖子进行即时评论,在发布新评论后,我在帖子下插入新评论以及删除 按钮。问题是 Delete 按钮在新插入的元素上不起作用,
我有一个大约有 20 列的“管道分隔”文件。我只想使用 sha1sum 散列第一列,它是一个数字,如帐号,并按原样返回其余列。 使用 awk 或 sed 执行此操作的最佳方法是什么? Accounti
我需要将以下内容插入到我的表中...我的用户表有五列 id、用户名、密码、名称、条目。 (我还没有提交任何东西到条目中,我稍后会使用 php 来做)但由于某种原因我不断收到这个错误:#1054 - U
所以我试图有一个输入字段,我可以在其中输入任何字符,但然后将输入的值小写,删除任何非字母数字字符,留下“。”而不是空格。 例如,如果我输入: 地球的 70% 是水,-!*#$^^ & 30% 土地 输
我正在尝试做一些我认为非常简单的事情,但出于某种原因我没有得到想要的结果?我是 javascript 的新手,但对 java 有经验,所以我相信我没有使用某种正确的规则。 这是一个获取输入值、检查选择
我想使用 angularjs 从 mysql 数据库加载数据。 这就是应用程序的工作原理;用户登录,他们的用户名存储在 cookie 中。该用户名显示在主页上 我想获取这个值并通过 angularjs
我正在使用 autoLayout,我想在 UITableViewCell 上放置一个 UIlabel,它应该始终位于单元格的右侧和右侧的中心。 这就是我想要实现的目标 所以在这里你可以看到我正在谈论的
我需要与 MySql 等效的 elasticsearch 查询。我的 sql 查询: SELECT DISTINCT t.product_id AS id FROM tbl_sup_price t
我正在实现代码以使用 JSON。 func setup() { if let flickrURL = NSURL(string: "https://api.flickr.com/
我尝试使用for循环声明变量,然后测试cols和rols是否相同。如果是,它将运行递归函数。但是,我在 javascript 中执行 do 时遇到问题。有人可以帮忙吗? 现在,在比较 col.1 和
我举了一个我正在处理的问题的简短示例。 HTML代码: 1 2 3 CSS 代码: .BB a:hover{ color: #000; } .BB > li:after {
我是一名优秀的程序员,十分优秀!