隊列類型
并發隊列(Concurrent Dispatch Queue)任務并發(同步)執行
串行隊列(Serial Dispatch Queue)任務順序執行
全局隊列(Global Queue)并發隊列
主隊列(Main Queue)串行隊列
/**
* lable : 隊列名稱
* attr : 隊列類型,并發(ConCurrent),串行(Serial 或 NULL)
*/
dispatch_queue_t conCurrentQueue = dispatch_queue_create("conCurrent", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t serialQueue = dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue1 = dispatch_queue_create("serial1", NULL);
/**
* 全局并發隊列
* identifier : 優先級
* flags : 設置為0即可
*/
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
/**
* 主隊列,串行隊列
*/
dispatch_queue_t mainQueue = dispatch_get_main_queue();
執行方式
同步執行-在當前線程執行
異步執行-在新線程執行
queue:隊列
block:任務,需要進行的操作
//同步任務
dispatch_sync(<#dispatch_queue_t queue#>, <#^(void)block#>)
//異步任務
dispatch_async(<#dispatch_queue_t queue#>, <#^(void)block#>)
代碼示例
- 異步任務 + 串行隊列
開啟新線程,串行執行任務。
dispatch_queue_t serialCurrentQueue = dispatch_queue_create("myQueue", NULL);
dispatch_async(serialCurrentQueue, ^{
NSLog(@"串行隊列-異步任務1-%@", [NSThread currentThread]);
});
dispatch_async(serialCurrentQueue, ^{
NSLog(@"串行隊列-異步任務2-%@", [NSThread currentThread]);
});
dispatch_async(serialCurrentQueue, ^{
NSLog(@"串行隊列-異步任務3-%@", [NSThread currentThread]);
});
dispatch_async(serialCurrentQueue, ^{
NSLog(@"串行隊列-異步任務4-%@", [NSThread currentThread]);
});
NSLog(@"執行完成");
/*
執行完成
串行隊列-異步任務1-<NSThread: 0x7f9f32e1de80>{number = 2, name = (null)}
串行隊列-異步任務2-<NSThread: 0x7f9f32e1de80>{number = 2, name = (null)}
串行隊列-異步任務3-<NSThread: 0x7f9f32e1de80>{number = 2, name = (null)}
串行隊列-異步任務4-<NSThread: 0x7f9f32e1de80>{number = 2, name = (null)}
*/
- 異步任務 + 并行隊列
開啟新線程,同步執行任務。
dispatch_queue_t conCurrentQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(conCurrentQueue, ^{
NSLog(@"并發隊列-異步任務1-%@", [NSThread currentThread]);
});
dispatch_async(conCurrentQueue, ^{
NSLog(@"并發隊列-異步任務2-%@", [NSThread currentThread]);
});
dispatch_async(conCurrentQueue, ^{
NSLog(@"并發隊列-異步任務3-%@", [NSThread currentThread]);
});
dispatch_async(conCurrentQueue, ^{
NSLog(@"并發隊列-異步任務4-%@", [NSThread currentThread]);
});
NSLog(@"執行完成");
/*
執行完成
并發隊列-異步任務1-<NSThread: 0x7fb751e1a6a0>{number = 5, name = (null)}
并發隊列-異步任務3-<NSThread: 0x7fb751d08830>{number = 6, name = (null)}
并發隊列-異步任務2-<NSThread: 0x7fb751d0ee50>{number = 2, name = (null)}
并發隊列-異步任務4-<NSThread: 0x7fb751d0f340>{number = 4, name = (null)}
或
并發隊列-異步任務2-<NSThread: 0x7fb751d01d20>{number = 10, name = (null)}
執行完成
并發隊列-異步任務1-<NSThread: 0x7fb751d06210>{number = 9, name = (null)}
并發隊列-異步任務3-<NSThread: 0x7fb751d0f400>{number = 11, name = (null)}
并發隊列-異步任務4-<NSThread: 0x7fb751d08830>{number = 8, name = (null)}
*/
- 異步任務 + 主線程
不開啟新線程,在主線程串行執行任務。
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(mainQueue, ^{
NSLog(@"主隊列-異步任務1-%@", [NSThread currentThread]);
});
dispatch_async(mainQueue, ^{
NSLog(@"主隊列-異步任務2-%@", [NSThread currentThread]);
});
dispatch_async(mainQueue, ^{
NSLog(@"主隊列-異步任務3-%@", [NSThread currentThread]);
});
dispatch_async(mainQueue, ^{
NSLog(@"主隊列-異步任務4-%@", [NSThread currentThread]);
});
NSLog(@"執行完成");
/*
執行完成
主隊列-異步任務1-<NSThread: 0x7f8ccb601ec0>{number = 1, name = main}
主隊列-異步任務2-<NSThread: 0x7f8ccb601ec0>{number = 1, name = main}
主隊列-異步任務3-<NSThread: 0x7f8ccb601ec0>{number = 1, name = main}
主隊列-異步任務4-<NSThread: 0x7f8ccb601ec0>{number = 1, name = main}
*/
- 同步任務 + 串行隊列
不開啟新線程,串行執行任務。
dispatch_queue_t serialCurrentQueue = dispatch_queue_create("myQueue", NULL);
dispatch_sync(serialCurrentQueue, ^{
NSLog(@"串行隊列-同步任務1-%@", [NSThread currentThread]);
});
dispatch_sync(serialCurrentQueue, ^{
NSLog(@"串行隊列-同步任務2-%@", [NSThread currentThread]);
});
dispatch_sync(serialCurrentQueue, ^{
NSLog(@"串行隊列-同步任務3-%@", [NSThread currentThread]);
});
dispatch_sync(serialCurrentQueue, ^{
NSLog(@"串行隊列-同步任務4-%@", [NSThread currentThread]);
});
NSLog(@"執行完成");
/*
串行隊列-同步任務1-<NSThread: 0x7f99c8600190>{number = 1, name = main}
串行隊列-同步任務2-<NSThread: 0x7f99c8600190>{number = 1, name = main}
串行隊列-同步任務3-<NSThread: 0x7f99c8600190>{number = 1, name = main}
串行隊列-同步任務4-<NSThread: 0x7f99c8600190>{number = 1, name = main}
執行完成
*/
- 同步任務 + 并行隊列
不開啟新線程,串行執行任務。
dispatch_queue_t conCurrentQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(conCurrentQueue, ^{
NSLog(@"并發隊列-同步任務1-%@", [NSThread currentThread]);
});
dispatch_sync(conCurrentQueue, ^{
NSLog(@"并發隊列-同步任務2-%@", [NSThread currentThread]);
});
dispatch_sync(conCurrentQueue, ^{
NSLog(@"并發隊列-同步任務3-%@", [NSThread currentThread]);
});
dispatch_sync(conCurrentQueue, ^{
NSLog(@"并發隊列-同步任務4-%@", [NSThread currentThread]);
});
NSLog(@"執行完成");
/*
并發隊列-同步任務1-<NSThread: 0x7fc1d2d08820>{number = 1, name = main}
并發隊列-同步任務2-<NSThread: 0x7fc1d2d08820>{number = 1, name = main}
并發隊列-同步任務3-<NSThread: 0x7fc1d2d08820>{number = 1, name = main}
并發隊列-同步任務4-<NSThread: 0x7fc1d2d08820>{number = 1, name = main}
執行完成
*/
- 同步任務 + 主隊列
阻塞主線程
dispatch_queue_t mainQueue = dispatch_get_main_queue();
NSLog(@"任務開始");
dispatch_sync(mainQueue, ^{
NSLog(@"主隊列-同步任務1-%@", [NSThread currentThread]);
});
NSLog(@"執行完成");
/*主隊列等待同步任務完成,同步任務等待主隊列執行完,相互等待,誰都完成不了。
任務開始
*/
表格總結
全局、并發隊列 | 自建串行隊列 | 主隊列 | |
---|---|---|---|
同步任務 | 不開啟新線程;串行執行任務 | 不開啟新線程;串行執行任務 | 造成死鎖 |
異步任務 | 開啟新線程;并發執行任務 | 開啟新線程;串行執行任務 | 不開啟新線程;串行執行任務 |
GCD調度組(線程組)
異步執行多個任務,當所有任務執行完成后,再執行某個任務。
代碼示例
GCD線程間通訊
主隊列=主線程=UI線程,所有的界面刷新都需要在主線程進行,子線程完成操作后,拿到主線程,在主線程進行刷新界面。
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
//執行耗時任務
//...
dispatch_async(dispatch_get_main_queue(), ^{
//在主線程進行界面刷新
//...
});
});
GCD延時函數
//第一種
[self performSelector:@selector(showMessage) withObject:nil afterDelay:2.0f];
//第二種
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//2秒后執行的操作
//...
});
GCD執行一次函數
提示方法
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//只需要執行一次的代碼
//...
});
GCD柵欄函數
在并發隊列插入柵欄函數,會先執行柵欄函數之前的操作,再執行柵欄函數,最后執行柵欄函數后面的操作,起到柵欄的作用。
dispatch_queue_t queue = dispatch_queue_create("name", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"耗時操作1-%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"耗時操作2-%@", [NSThread currentThread]);
});
dispatch_barrier_async(queue, ^{
NSLog(@"柵欄函數-%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"耗時操作3-%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"耗時操作4-%@", [NSThread currentThread]);
});
NSLog(@"執行完成");
/*
執行完成
耗時操作2-<NSThread: 0x7ff4b2dad620>{number = 2, name = (null)}
耗時操作1-<NSThread: 0x7ff4b2c04bc0>{number = 3, name = (null)}
柵欄函數-<NSThread: 0x7ff4b2c04bc0>{number = 3, name = (null)}
耗時操作4-<NSThread: 0x7ff4b2dad620>{number = 2, name = (null)}
耗時操作3-<NSThread: 0x7ff4b2c04bc0>{number = 3, name = (null)}
*/
GCD-dispatch_apply()函數
提交任務到隊列中多次執行,由隊列決定并行還是串行。dispatch_apply為同步任務,執行完dispatch_apply才會執行下面的操作。
/* iterations 執行的次數
queue 提交到的隊列
size_t 索引,需要自己指定一個參數
block 執行的任務
dispatch_apply(size_t iterations, dispatch_queue_t queue, <#^(size_t)block#>)
*/
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
dispatch_apply(4, globalQueue, ^(size_t index) {
//執行的循環操作
NSLog(@"次數%d-%@", index, [NSThread currentThread]);
});
NSLog(@"執行完成");
/*
次數0-<NSThread: 0x7f9da35020d0>{number = 1, name = main}
次數1-<NSThread: 0x7f9da340be60>{number = 2, name = (null)}
次數3-<NSThread: 0x7f9da3740740>{number = 4, name = (null)}
次數2-<NSThread: 0x7f9da3608440>{number = 3, name = (null)}
執行完成
*/