//
// GCD_ViewController.m
// ZM_NSThreadGCD
//
// Created by ZM on 2015/2/9.
// Copyright © 2015
年
ZM. All rights reserved.
//
#import
"GCD_ViewController.h"
#import
"BaseHeader.h"
@interface
GCD_ViewController
()
@end
@implementation
GCD_ViewController
- (
void
)viewDidLoad {
[
super
viewDidLoad
];
self
.
title
=
@"GCD_VC"
;
NSString
*title=
@""
;
CGFloat
width =
120
;
for
(
int
i=
1
; i<
11
; i++) {
title = [
NSString
stringWithFormat
:
@"case%d"
,i];
[
self
addBtnTitle
:title
frame
:
CGRectMake
(
10
,
50
+ (
35
+
10
)*i, width,
35
)
Tag
:i];
}
CGFloat
yy =
SSHEIGHT
-
90
;
[
self
addBtnTitle
:
@"attentionCase3_1"
frame
:
CGRectMake
(
10
, yy, width,
35
)
Tag
:
111
];
[
self
addBtnTitle
:
@"attentionCase3_2"
frame
:
CGRectMake
(
10
*
2
+width, yy, width,
35
)
Tag
:
222
];
[
self
addBtnTitle
:
@"solveCase3_1"
frame
:
CGRectMake
(
10
, yy+
45
, width,
35
)
Tag
:
333
];
}
- (
void
)myBtnClick:(
UIButton
*)Btn{
if
(Btn.
tag
==
1
) { [
self
case1
];
}
else
if
(Btn.
tag
==
2
) { [
self
case2
];
}
else
if
(Btn.
tag
==
3
) { [
self
case3
];
}
else
if
(Btn.
tag
==
4
) { [
self
case4
];
}
else
if
(Btn.
tag
==
5
) { [
self
case5
];
}
else
if
(Btn.
tag
==
6
) { [
self
case6
];
}
else
if
(Btn.
tag
==
7
) { [
self
case7
];
}
else
if
(Btn.
tag
==
8
) { [
self
case8
];
}
else
if
(Btn.
tag
==
9
) { [
self
case9
];
}
if
(Btn.
tag
==
111
) { [
self
attentionCase3_1
];
}
else
if
(Btn.
tag
==
222
) { [
self
attentionCase3_2
];
}
else
if
(Btn.
tag
==
333
) { [
self
solveCase3_1
];
}
}
/**
*
以下
4
个
GCD
方法的区别:
dispatch_async
异步任务
dispatch_sync
同步任务
dispatch_barrier_async
为异步执行调度队列:提交一个路障
dispatch_barrier_sync
为同步执行调度队列:提交一个路障
dispatch_get_main_queue
主队列
dispatch_queue_t
并行队列
dispatch_get_global_queue
全局并行队列
*/
//
例一:
dispatch_sync
同步任务
提交
Block
在
主线程
中执行
- (
void
)case1 {
dispatch_queue_t
queue1 =
dispatch_queue_create
(
"
并行
"
,
DISPATCH_QUEUE_CONCURRENT
);
dispatch_sync
(queue1, ^{
NSLog
(
@"%@"
,[
NSThread
currentThread
]);
//
输出结果:
{number = 1, name = main}
});
}
//
例二:
dispatch_async
异步任务
提交
Block
在
分线程
中执行
- (
void
)case2 {
dispatch_queue_t
queue1 =
dispatch_queue_create
(
"
并行
"
,
DISPATCH_QUEUE_CONCURRENT
);
dispatch_async
(queue1, ^{
NSLog
(
@"%@"
,[
NSThread
currentThread
]);
//
输出结果:
{number = 3, name = (null)}
});
}
//
例三:我们分别用
sync
和
async
向主队列提交
Block
,结果
Block
都是在主线程中执行:
- (
void
)case3 {
//
我们用
sync
如下的方式去提交
Block
:
dispatch_queue_t
queue1 =
dispatch_queue_create
(
"
并行
"
,
DISPATCH_QUEUE_CONCURRENT
);
dispatch_async
(queue1, ^{
dispatch_sync
(
dispatch_get_main_queue
(), ^{
NSLog
(
@"%@"
,[
NSThread
currentThread
]);
//
输出结果:
{number = 1, name = main}
});
});
}
//
注意
3_1
:在主线程
不能用
sync
(同步)提交
Block
执行任务,否则会引起死锁:
- (
void
)attentionCase3_1 {
dispatch_sync
(
dispatch_get_main_queue
(), ^{
NSLog
(
@"
任务一
"
);
});
NSLog
(
@"
任务二
"
);
//
因为往
queue
中提交
Block
,总是追加在队列尾部的,而
queue
执行
Block
的顺序为先进先出(
FIFO
),所以任务一需要在当前队列它之前的任务(任务二)全部执行完,才能轮到它。
//
任务一等待任务二完成,任务二等待任务一完成,相互等待
_
被阻塞,程序被死锁在这了
}
//
注意
3_2
:在主线程
能用
async
(异步)提交
Block
执行任务
- (
void
)attentionCase3_2 {
dispatch_async
(
dispatch_get_main_queue
(), ^{
NSLog
(
@"%@"
,[
NSThread
currentThread
]);
//
输出结果:
{number = 1, name = main}
});
}
//
解决
3_1
问题
- (
void
)solveCase3_1 {
//
全局并行队列
//
这应该是唯一一个并行队列,
只要是并行任务一般都加入到这个队列。这是系统提供的一个并发队列。
//
因为全局队列和主队列是两个队列,所以任务一的执行,并不需要等待任务二。
dispatch_sync
(
dispatch_get_global_queue
(
0
,
0
), ^{
NSLog
(
@"
任务一
"
);
});
NSLog
(
@"
任务二
"
);
}
//
例四:
建立栅栏
_
执行任务
dispatch_barrier_async
- (
void
)case4 {
dispatch_queue_t
queue =
dispatch_queue_create
(
"queue"
,
DISPATCH_QUEUE_CONCURRENT
);
dispatch_async
(queue, ^{
NSLog
(
@"
任务
1"
);
});
dispatch_async
(queue, ^{
NSLog
(
@"
任务
2"
);
});
dispatch_async
(queue, ^{
NSLog
(
@"
任务
3"
);
});
//
建立栅栏
_
执行任务
dispatch_barrier_async
dispatch_barrier_async
(queue, ^{
NSLogline
(
@"\n %@\n %@\n %@"
,
@"
任务
1
,
2
,
3
的顺序不一定
"
,
@"
任务
4_
在中间
"
,
@"
最后是
5
、
6
、
7
、
8
、
9
任务顺序不一定
"
);
});
dispatch_async
(queue, ^{
NSLog
(
@"
任务
5"
);
});
dispatch_async
(queue, ^{
NSLog
(
@"
任务
6"
);
});
dispatch_async
(queue, ^{
NSLog
(
@"
任务
7"
);
});
dispatch_async
(queue, ^{
NSLog
(
@"
任务
8"
);
});
dispatch_async
(queue, ^{
NSLog
(
@"
任务
9"
);
});
//
结论:
dispatch_barrier_async
它的作用可以用一个词概括--承上启下,它保证此前的任务都先于自己执行,此后的任务也迟于自己执行。当然它的作用导致它只有在并行队列中有意义。
//
注意:当然这里有一点需要注意的是:
dispatch_barrier_(a)sync
只在自己创建的并发队列上有效,在全局
(Global)
并发队列、串行队列上,效果跟
dispatch_(a)sync
效果一样。
//3)dispatch_barrier_sync
这个方法和
dispatch_barrier_async
作用几乎一样,都可以在并行
queue
中当做栅栏。
//
唯一的区别就是:
dispatch_barrier_sync
有
GCD
的
sync
共有特性,会阻塞提交
Block
的当前线程,而
dispatch_barrier_async
是异步提交,不会阻塞。
}
//
例五:例如我们在一个读写操作中
,
我们就可以如下使用:
- (
void
)case5 {
//
一个读写操作中:我们要知道一个数据,读与读之间是可以用线程并行的,但是写与写、写与读之间,就必须串行同步或者使用线程锁来保证线程安全。但是我们有了
dispatch_barrier_async
dispatch_queue_t
queue =
dispatch_queue_create
(
"queue"
,
DISPATCH_QUEUE_CONCURRENT
);
dispatch_async
(queue, ^{
NSLog
(
@"
读操作
_1"
);
});
dispatch_async
(queue, ^{
NSLog
(
@"
读操作
_2"
);
});
dispatch_barrier_async
(queue, ^{
NSLog
(
@"
写操作
_1"
);
});
dispatch_barrier_async
(queue, ^{
NSLog
(
@"
写操作
_2"
);
});
dispatch_async
(queue, ^{
NSLog
(
@"
读操作
"
);
});
//
结论:这样写操作的时候,始终只有它这一条线程在进行。而读操作一直是并行的。这么做充分利用了多线程的优势,还不需要加锁,减少了相当一部分的性能开销。实现了读写操作的线程安全。
//
读与读
:
线程并行
//
写与写、写与读
:
必须串行同步或者使用线程锁
}
//
例六:
4
)
dispatch_sync
,我们来讲讲它和
dispatch_barrier_sync
的区别。二者因为是
sync
提交,所以都是阻塞当前提交
Block
线程。
//
而它俩唯一的区别是:
dispatch_sync
并不能阻塞并行队列。其实之前死锁有提及过,担心大家感觉疑惑,还是写个例子:
- (
void
)case6 {
dispatch_queue_t
queue =
dispatch_queue_create
(
"
并行
"
,
DISPATCH_QUEUE_CONCURRENT
);
// dispatch_sync
dispatch_sync
(queue, ^{
dispatch_async
(queue, ^{
NSLog
(
@"
任务二
"
);
});
dispatch_async
(queue, ^{
NSLog
(
@"
任务三
"
);
});
//
睡眠
2
秒
// [NSThread sleepForTimeInterval:2];
NSLog
(
@"
任务一
\n "
);
});
//
输出结果
:
任务三
任务二
任务一
(二、三顺序不固定,一最后,很显然,并行队列没有被
sync
所阻塞。)
}
//
例七:而
dispatch_barrier_sync
可以阻塞并行队列(栅栏作用的体现):
- (
void
)case7 {
dispatch_queue_t
queue =
dispatch_queue_create
(
"
并行
"
,
DISPATCH_QUEUE_CONCURRENT
);
// dispatch_barrier_sync
dispatch_barrier_sync
(queue, ^{
dispatch_async
(queue, ^{
NSLog
(
@"
任务二
"
);
});
dispatch_async
(queue, ^{
NSLog
(
@"
任务三
"
);
});
//
睡眠
2
秒
// [NSThread sleepForTimeInterval:2];
NSLog
(
@"
任务一
"
);
});
//
输出结果
:
任务一
任务二
任务三
(一首先,二、三顺序不固定)
}
/**
同:
dispatch_sync
、
dispatch_barrier_sync
都能阻塞
主队列
区别:
dispatch_sync
不能阻塞并行队列
dispatch_barrier_sync
可以阻塞并行队列
*/
- (
void
)case8 {
}
- (
void
)case9 {
}
@end