GCD概述:
OC:
/*
GCD:Grand Central Dispatch 牛X的中樞調度器,C語言編寫
GCD:自動管理線程的生命周期,(創建, 調度任務, 銷毀線程)
任務:block (1.定制任務)
隊列:queue (2.任務添加到隊列)
GCD自動從隊列queue中取出任務block執行,遵循FIFO原則,先進先出
任務block執行方式:
同步的(synchronous ['s??kr?n?s]):不能開新線程
dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
異步的(asynchronous [e's??kr?n?s]):能開新線程
dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
隊列queue:
并發隊列(Concurrent Dispatch Queue):
[DISPATCH_QUEUE_CONCURRENT];
讓多個任務并發執行,自動開啟多個線程同時執行任務;
該功能只在異步函數(dispatch_async)下有效;
串行隊列(Serial Dispatch Queue):
[DISPATCH_QUEUE_SERIAL];
讓任務順序執行;
隊列queue的創建:
并發隊列:
方式1.dispatch_queue_create(const char *label, dispatch_queue_attr_a attr)
label:表示該隊列的名字(標識), C語言中的字符串,創建的時候直接"abcde";
attr:表示隊列屬性,設置并發or串行,此處使用并發(DISPATCH_QUEUE_CONCURRENT)
方式2:獲取全局并發隊列
dispatch_get_global_queue(dispatch_queue_priority_t priority, unsigned long flags);
priority:隊列的優先級(高,默認,低,后臺)
flags:此參數暫時無用,用0即可
串行隊列:
方式1.dispatch_queue_create(const char *label, dispatch_queue_attr_a attr)
label:表示該隊列的名字(標識);
attr:表示隊列屬性,設置并發or串行,此處使用串行(DISPATCH_QUEUE_SERIAL or NULL)
方式2:使用主隊列,與主線程相關聯的隊列
主隊列是GCD自帶的一種特殊的串行隊列;該隊列中的任務,都會在主線程中執行;
dispatch_get_main_queue();
*/
相關練習:
#pragma mark - 并發隊列,同步任務: 沒有開啟新線程,任務按添加順序依次執行;
- (void)concurrentSync {
// A.創建并發隊列concurrentQueue:
char *queueName = "ConcurrentQueue";
dispatch_queue_t concurrentQueue = dispatch_queue_create(queueName, DISPATCH_QUEUE_CONCURRENT);
// B.創建任務block
// 方式一: 定義一個block類型,命名為TestBlock1,然后只用該類型聲明變量block1
// 1.定義一個block的類型,返回值void,參數為空,命名為Block1,(類似于 int),
typedef void (^TestBlock1)();
// 2.使用Block1類型定義一個變量block, 同時做賦值操作,賦值的內容為后面的代碼段(^{...})
TestBlock1 block1 = ^{
// 這是里block中的操作
for (int i = 0; i < 5; i++) {
NSLog(@"---block1---%@", [NSThread currentThread]);
}
};
// 方式二: 直接定義一個名為block的block2變量
void (^block2)() = ^{
// 這是里block中的操作
for (int i = 0; i < 5; i++) {
NSLog(@"---block2---%@", [NSThread currentThread]);
}
};
// C.給并發隊列concurrentQueue,添加同步任務dispatch_sync
// 方式1: block1變量
dispatch_sync(concurrentQueue, block1);
// 方式2: block2變量
dispatch_sync(concurrentQueue, block2);
// 方式3: 直接添加block
dispatch_sync(concurrentQueue, ^{
// 這是里block中的操作
for (int i = 0; i < 5; i++) {
NSLog(@"---block--3---%@", [NSThread currentThread]);
}
});
}
#pragma mark - 并發隊列,異步任務: 開啟新線程,任務并發執行
- (void)concurrentAsync {
// 1.創建并發隊列 DISPATCH_QUEUE_CONCURRENT
char *queueName = "ConcurrentQueue";
dispatch_queue_t concurrentQueue = dispatch_queue_create(queueName, DISPATCH_QUEUE_CONCURRENT);
// 2.創建任務block
typedef void (^TestBlock)();
TestBlock block = ^{
// 這是里block中的操作
for (int i = 0; i < 5; i++) {
NSLog(@"---block1---%@", [NSThread currentThread]);
}
};
void (^block2)() = ^{
// 這是里block中的操作
for (int i = 0; i < 5; i++) {
NSLog(@"---block2---%@", [NSThread currentThread]);
}
};
// 3.并發隊列concurrent,添加異步任務async;
dispatch_async(concurrentQueue, block);
dispatch_async(concurrentQueue, block2);
dispatch_async(concurrentQueue, ^{
// 這是里block中的操作
for (int i = 0; i < 5; i++) {
NSLog(@"---3---%@", [NSThread currentThread]);
}
});
}
#pragma mark - 全局隊列,同步任務: 沒有開啟新線程,任務按添加順序依次執行;
- (void)globalSync {
//全局隊列的優先級
#define DISPATCH_QUEUE_PRIORITY_HIGH 2
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0
#define DISPATCH_QUEUE_PRIORITY_LOW (-2)
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN
typedef long dispatch_queue_priority_t;
// 1.獲取全局隊列 DISPATCH_QUEUE_PRIORITY_DEFAULT or 0 都可以
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 2.創建任務block
typedef void (^TestBlock1)();
TestBlock1 block1 = ^{
for (int i = 0; i < 5; i++) {
NSLog(@"---block1---%@", [NSThread currentThread]);
}
};
void (^block2)() = ^{
for (int i = 0; i < 5; i++) {
NSLog(@"---block2---%@", [NSThread currentThread]);
}
};
// 3.給全局隊列globalQueue,添加同步任務dispatch_sync
dispatch_sync(globalQueue, block1);
dispatch_sync(globalQueue, block2);
dispatch_sync(globalQueue, ^{
for (int i = 0; i < 5; i++) {
NSLog(@"---block--3---%@", [NSThread currentThread]);
}
});
}
#pragma mark - 全局隊列,異步任務: 開啟新線程,任務并發執行;
- (void)globalAsync {
// 1.獲取全局隊列 DISPATCH_QUEUE_PRIORITY_DEFAULT or 0 都可以
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
// 2.創建任務
typedef void (^TestBlock)();
TestBlock block = ^{
for (int i = 0; i < 5; i++) {
NSLog(@"---block1---%@", [NSThread currentThread]);
}
};
void (^block2)() = ^{
for (int i = 0; i < 5; i++) {
NSLog(@"---block2---%@", [NSThread currentThread]);
}
};
// 3.全局隊列globalQueue,添加異步任務;
dispatch_async(globalQueue, block);
dispatch_async(globalQueue, block2);
dispatch_async(globalQueue, ^{
for (int i = 0; i < 5; i++) {
NSLog(@"---3---%@", [NSThread currentThread]);
}
});
}
#pragma mark - 串行隊列,同步任務: 沒有開啟新線程,任務按添加順序依次執行;
- (void)serialSync {
char *queueName = "SerialQueue";
// 串行隊列 DISPATCH_QUEUE_SERIAL or NULL
dispatch_queue_t serialQueue = dispatch_queue_create(queueName, DISPATCH_QUEUE_SERIAL);
// 創建任務block
typedef void (^TestBlock1)();
TestBlock1 block1 = ^{
for (int i = 0; i < 5; i++) {
NSLog(@"---block1---%@", [NSThread currentThread]);
}
};
void (^block2)() = ^{
for (int i = 0; i < 5; i++) {
NSLog(@"---block2---%@", [NSThread currentThread]);
}
};
// 給串行隊列serialQueue,添加同步任務dispatch_sync
dispatch_sync(serialQueue, block1);
dispatch_sync(serialQueue, block2);
dispatch_sync(serialQueue, ^{
for (int i = 0; i < 5; i++) {
NSLog(@"---block--3---%@", [NSThread currentThread]);
}
});
}
#pragma mark - 串行隊列,異步任務: 開啟新線程,任務按添加順序依次執行;
- (void)serialAsync {
// 1.創建隊列queue
char *queueName = "SerialQueue";
dispatch_queue_t serialQueue = dispatch_queue_create(queueName, NULL);
// 2.創建任務block
typedef void (^TestBlock1)();
TestBlock1 block1 = ^{
for (int i = 0; i < 5; i++) {
NSLog(@"---block1---%@", [NSThread currentThread]);
}
};
void (^block2)() = ^{
for (int i = 0; i < 5; i++) {
NSLog(@"---block2---%@", [NSThread currentThread]);
}
};
// 3.串行隊列serialQueue, 添加異步任務
dispatch_async(serialQueue, block1);
dispatch_async(serialQueue, block2);
dispatch_async(serialQueue, ^{
for (int i = 0; i < 5; i++) {
NSLog(@"---block--3---%@", [NSThread currentThread]);
}
});
}
#pragma mark - 主隊列, 同步任務: 死鎖
- (void)mainSync {
NSLog(@"%s", "主隊列mai zhuduilie, 同步任務sync tongburenwu, 會造成死鎖 huizaochengsisuo");
// 1.獲得主隊列main
dispatch_queue_t mainQueue = dispatch_get_main_queue();
// 2.創建任務block
typedef void (^TestBlock1)();
TestBlock1 block1 = ^{
for (int i = 0; i < 5; i++) {
NSLog(@"---block1---%@", [NSThread currentThread]);
}
};
void (^block2)() = ^{
for (int i = 0; i < 5; i++) {
NSLog(@"---block2---%@", [NSThread currentThread]);
}
};
// 3.給主隊列mainQueue,添加同步任務dispatch_sync
dispatch_sync(mainQueue, block1);
dispatch_sync(mainQueue, block2);
dispatch_sync(mainQueue, ^{
for (int i = 0; i < 5; i++) {
NSLog(@"---block--3---%@", [NSThread currentThread]);
}
});
// 死鎖導致block中的內容都不會執行
}
/*
GCD Queue 分為三種:
1,The main queue:主隊列,主線程就是在個隊列中。
2,Global queues: 全局并發隊列。
3,用戶隊列:是用函數 dispatch_queue_create 創建的自定義隊列
dispatch_sync 和 dispatch_async 區別:
dispatch_async(queue,block) async 異步隊列,dispatch_async 函數會立即返回, block會在后臺異步執行。
dispatch_sync(queue,block) sync 同步隊列,dispatch_sync 函數不會立即返回,及阻塞當前線程,等待block同步執行完成。
分析:
在主線程中,即dispatch_get_main_queue()中,執行到sync時向dispatch_get_main_queue()插入同步block1.
sync會等到后面block1執行完成才返回,sync又在dispatch_get_main_queue() 隊列中,它是串行隊列,sync是后加入的,
前一個是主線程,所以sync想執行block必須等待主線程執行完成,主線程等待sync返回,去執行后續內容。
造成死鎖,sync等待main執行完成,mian等待sync函數返回。
*/
#pragma mark - 主隊列,異步任務: 沒有開啟新線程,任務按添加順序依次執行;
- (void)mainAsync {
// 1.獲取主隊列main
dispatch_queue_t mainQueue = dispatch_get_main_queue();
// 2.創建任務block
typedef void (^TestBlock1)();
TestBlock1 block1 = ^{
for (int i = 0; i < 5; i++) {
NSLog(@"---block1---%@", [NSThread currentThread]);
}
};
void (^block2)() = ^{
for (int i = 0; i < 5; i++) {
NSLog(@"---block2---%@", [NSThread currentThread]);
}
};
// 3.給主隊列mainQueue,添加異步任務dispatch_async
dispatch_async(mainQueue, block1);
dispatch_async(mainQueue, block2);
dispatch_async(mainQueue, ^{
for (int i = 0; i < 5; i++) {
NSLog(@"---block--3---%@", [NSThread currentThread]);
}
});
}
#pragma mark -
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
/***********************************************************/
// 定義block的兩種方式之一:
// 定義
// 參考范例,返回值int,參數(int, int)(沒有參數名,匿名),名稱Test
typedef int (^Test1)(int, int);
// 使用Test初始化一個變量test
Test1 test1 ;
// 實現
test1 = ^(int x, int y) {
return x + y;
};
// 調用
int result = test1(1, 2); //result = 3;
NSLog(@"%d", result);
/////////
// 初始化變量,實現,同時進行
Test1 test = ^(int x, int y) {
return x + y;
};
// 調用
NSLog(@"%d", test(100, 200));
/***********************************************************/
// 定義block的兩種方式之二:
// 定義,實現,合并進行
// 直接定義一個變量test2,參數(int, int)(沒有參數名,匿名),名稱Test
int (^test2)(int, int) = ^(int x, int y){
return x + y;
};
NSLog(@"%d", test2(10, 20)); //result = 30;
/***********************************************************/
}
Swift 3.0:
/**
GCD:Grand Central Dispatch 牛X的中樞調度器
GCD:自動管理線程的生命周期,(創建, 調度任務, 銷毀線程)
任務:閉包closure or DispatchWorkItem
隊列:DispatchQueue
GCD自動從隊列中取出任務執行,遵循FIFO原則,先進先出
任務執行方式:
同步(synchronous ['s??kr?n?s]):不能開新線程
DispatchQueue.global().sync {
// 同步執行
}
異步(asynchronous [e's??kr?n?s]):能開新線程
DispatchQueue.global().async {
// code
DispatchQueue.main.async {
// 主線程中
}
}
隊列DispatchQueue:
DispatchQueue的默認初始化方法創建的就是一個串行隊列,如果要創建并發的隊列,在attributes中聲明concurrent。
label:表示該隊列的名字(標識);
attributes:表示隊列屬性,默認為串行,
同步隊列
let serialQueue = DispatchQueue(label: "QueueName")
讓任務順序執行;
主隊列
let mainQueue = DispatchQueue.main
并發隊列
let concurrentQueue = DispatchQueue(label: "QueueName", attributes: .concurrent)
讓多個任務并發執行,自動開啟多個線程同時執行任務;
全局并發隊列
let globalQueue = DispatchQueue.global(qos: .default)
let globalQueue = DispatchQueue.global()
// global 有默認的參數default, 如需改變優先級,則輸入對應的枚舉即可
*/
相關練習:
// MARK: - 并發Concurrent,同步sync,沒有開啟新線程,任務在主隊列main依次執行;
func concurrentSync() -> Void {
// 創建并發隊列
let concurrentQueue = DispatchQueue(label: "ConcurrentQueue", attributes: .concurrent)
// 任務類型
typealias Task = () -> Void
// Task類型的變量
let task1: Task
// 任務實現
task1 = {
print("concurrentSync task1...", Thread.current)
}
let task2: () -> Void = {
print("concurrentSync task2...", Thread.current)
}
// 并發隊列Concurrent,同步sync執行
concurrentQueue.sync(execute: task1) // main
concurrentQueue.sync(execute: task2) // main
concurrentQueue.sync {
print("concurrentSync task3...", Thread.current)
} // main
}
// MARK: - 并發Concurrent,異步async,開啟新線程,任務并發執行;
func concurrentAsync() -> Void {
// 隊列(并發concurrent)
let concurrentQueue = DispatchQueue(label: "ConcurrentQueue", attributes: .concurrent)
// 任務(閉包 or block)
typealias Task = () -> Void
let task1: Task = {
print("concurrentAsync-task1...", Thread.current)
}
let task2: () -> Void = {
print("concurrentAsync-task2...", Thread.current)
}
// 并發,異步
concurrentQueue.async(execute: task1) // new 1
concurrentQueue.async(execute: task2) // new 2
concurrentQueue.async {
print("concurrentAsync-task3...", Thread.current)
} // new 3
}
// MARK: - 全局global,同步sync,沒有開啟新線程,任務在主隊列main依次執行;
func globalSync() -> Void {
typealias Task = () -> Void
let task1: Task = {
print("globalSync...task1...", Thread.current)
}
let task2: () -> Void = {
print("globalSync...task2...", Thread.current)
}
/**
* global優先級的新舊枚舉值對應
* DISPATCH_QUEUE_PRIORITY_HIGH: .userInitiated
* DISPATCH_QUEUE_PRIORITY_DEFAULT: .default
* DISPATCH_QUEUE_PRIORITY_LOW: .utility
* DISPATCH_QUEUE_PRIORITY_BACKGROUND: .background
*/
// public class func global(qos: DispatchQoS.QoSClass = default) -> DispatchQueue
// global 有默認的參數default, 如需改變優先級,則輸入對應的枚舉即可
DispatchQueue.global(qos: .userInteractive).sync(execute: task1) // main 1
DispatchQueue.global(qos: .userInteractive).sync(execute: task2) // main 2
DispatchQueue.global(qos: .userInteractive).sync {
print("globalSync...task3...", Thread.current)
} // main 3
}
// MARK: - 全局global,異步async,開啟新線程,任務并發執行;
func globalAsync() -> Void {
typealias Task = () -> Void
let task1: Task = {
print("globalAsync...task1...", Thread.current)
}
let task2: Task = {
print("globalAsync...task2...", Thread.current)
}
DispatchQueue.global().async(execute: task1) // new 1
DispatchQueue.global().async(execute: task2) // new 2
DispatchQueue.global().async {
print("globalAsync...task3...", Thread.current)
} // new 3
}
/// 線程任務
typealias ThreadTask = () -> Void
// MARK: - 串行serial,同步sync,沒有開啟新線程,任務按順序執行;
func serialSync() -> Void {
// 隊列
let serialQueue = DispatchQueue(label: "SerialQueue")
// 任務
let task1: ThreadTask = {
print("serialSync...task1...", Thread.current)
}
let task2: ThreadTask = {
print("serialSync...task2...", Thread.current)
}
let task3: ThreadTask = {
print("serialSync...task3...", Thread.current)
}
// 串行,同步
serialQueue.sync(execute: task1) // main 1
serialQueue.sync(execute: task2) // main 2
serialQueue.sync(execute: task3) // main 3
}
// MARK: - 串行Serial,異步async,開啟新線程,任務按順序執行
func serialAsync() -> Void {
// 隊列
let serialQueue = DispatchQueue(label: "SerialQueue")
// 任務
let task1: ThreadTask = {
print("serialSync...task1...", Thread.current)
}
let task2: ThreadTask = {
print("serialSync...task2...", Thread.current)
}
let task3: ThreadTask = {
print("serialSync...task3...", Thread.current)
}
// 串行,異步
serialQueue.async(execute: task1) // new 1
serialQueue.async(execute: task2) // new 2
serialQueue.async(execute: task3) // new 3
}
// MARK: - 主隊列main,同步sync,死鎖
func mainSync() -> Void {
// 隊列
let mainQueue = DispatchQueue.main
// 任務
let task1: ThreadTask = {
print("serialSync...task1...", Thread.current)
}
let task2: ThreadTask = {
print("serialSync...task2...", Thread.current)
}
let task3: ThreadTask = {
print("serialSync...task3...", Thread.current)
}
// 主隊列,同步
mainQueue.sync(execute: task1) // 死鎖 x
mainQueue.sync(execute: task2) // x
DispatchQueue.main.sync(execute: task3) // x
}
// MARK: - 主隊列main,異步async,不開啟新線程,任務依次執行
func mainAsync() -> Void {
let mainQueue = DispatchQueue.main
let task1: ThreadTask = {
print("serialSync...task1...", Thread.current)
}
let task2: ThreadTask = {
print("serialSync...task2...", Thread.current)
}
let task3: ThreadTask = {
print("serialSync...task3...", Thread.current)
}
mainQueue.async(execute: task1) // main 1
mainQueue.async(execute: task2) // main 2
DispatchQueue.main.async(execute: task3) // main 3
}
// MARK: - 閉包測試
func closureTest() -> Void {
// 閉包回顧
/***********************************************************/
// 定義, 有3+參, 有返回值
typealias Test = (Int, Int, Int) -> Int
// 聲明變量test1
var test1: Test
// 實現
test1 = { x, y, z in
// 閉包中的操作
print("有3+參, 有返回值 test1...111")
return x + y + z
}
// 調用
print("test1...", test1(1, 2, 3))
// 聲明,實現
let test2: Test = {
// 閉包中的操作
print("有3+參, 有返回值 test2...222")
return $0 + $1 + $2
}
// 調用
print("test2...", test2(10, 20, 30))
/***********************************************************/
// 定義, 有2參, 有返回值
var test3: (Int, Int) -> Int
// 實現
test3 = (+)
// 調用
print("有2參, 有返回值 test3...", test3(100, 200))
/***********************************************************/
// 定義,無參,有返回值
var test4: () -> Int
// 實現
test4 = {
// 閉包中的操作
print("無參,有返回值 test4... 444")
return 12345
}
// 調用
print("test4...", test4())
/***********************************************************/
// 定義,無參,無返回值
let test5: () -> Void = {
// 相關操作
print("無參,有返回值 test5... 555")
}
test5()
/***********************************************************/
}
參考資料:
http://www.lxweimin.com/p/fc78dab5736f
http://www.lxweimin.com/p/28044b17f94b
https://www.logcg.com/archives/2040.html
https://github.com/future-challenger/Swift3.0/blob/master/GCD/README.md
https://my.oschina.net/doxing/blog/618132
http://v.youku.com/v_show/id_XMTU5MDg1MTE0NA==.html
http://v.youku.com/v_show/id_XMTU5MDg0OTY1Mg==.html