iOS GCD學習記錄
1,對於建立全域性使用的序列或者並行佇列,都應該用strong修飾,例如
- @property (nonatomic,strong) dispatch_queue_t dispatch_serial
這是因為在ios6.0之前,oc是沒辦法自動管理gcd佇列的,所以在iOS6.0之前要使用assign。但是iOS6.0之後,蘋果在oc裡面加入了自動管理gcd的功能。
2,有關內容的學習
這裡首先要記住
序列佇列是:DISPATCH_QUEUE_SERIAL
並行佇列是:DISPATCH_QUEUE_CONCURRENT
同步執行:dispatch_sync(<這裡寫是序列還是並行>, {<程式碼要完成的事>})
非同步執行:dispatch_async(<這裡寫是序列還是並行>, {<程式碼要完成的事>})
注:只要是非同步執行都會建立新的執行緒,同步執行不會建立新的執行緒。序列佇列肯定是上一個任務執行完才會執行下一個任務,並行佇列理論上可以說是同時執行,任務完成的順序和cpu的分配有關
首選宣告兩個全域性使用的佇列,一個序列佇列,一個並行佇列
@property (nonatomic,strong) dispatch_queue_t dispatch_serial;/**<序列佇列*/
@property (nonatomic,strong) dispatch_queue_t dispatch_concurrent;/**<並行佇列*/
在viewDidLoad裡面建立這兩個佇列
- (void)viewDidLoad {
[super viewDidLoad];
//建立兩個佇列
_dispatch_serial = dispatch_queue_create("dispatch_serial", DISPATCH_QUEUE_SERIAL);
_dispatch_concurrent = dispatch_queue_create("dispatch_concurrent", DISPATCH_QUEUE_CONCURRENT);
[self serialAndSynchronize];
[self serialAndASynchronize];
[self concurrentAndSynchronize];
[self concurrentAndASynchronize];
}
下面就是對不同情況下簡單的使用
序列同步佇列
//序列同步佇列
-(void)serialAndSynchronize{
dispatch_sync(_dispatch_serial, ^{
NSLog(@"1---------%@",[NSThread currentThread]);
});
dispatch_sync(_dispatch_serial, ^{
NSLog(@"2---------- %@",[NSThread currentThread]);
});
dispatch_sync(_dispatch_serial, ^{
NSLog(@"3---------- %@",[NSThread currentThread]);
});
NSLog(@"4------------ %@",[NSThread currentThread]);
}
列印的資料
2017-08-31 14:23:52.340 SYGCDStudy[8903:207494] 1---------<NSThread: 0x60000006c700>{number = 1, name = main}
2017-08-31 14:23:52.340 SYGCDStudy[8903:207494] 2---------- <NSThread: 0x60000006c700>{number = 1, name = main}
2017-08-31 14:23:52.340 SYGCDStudy[8903:207494] 3---------- <NSThread: 0x60000006c700>{number = 1, name = main}
2017-08-31 14:23:52.341 SYGCDStudy[8903:207494] 4------------ <NSThread: 0x60000006c700>{number = 1, name = main}
這裡可以看到。序列同步佇列實際上都是在主執行緒上面執行的,而且沒有建立新的執行緒,並行都是按照順序執行的,必須等前一個執行結束,才會執行下一個
序列非同步佇列
//序列非同步佇列
-(void)serialAndASynchronize{
dispatch_async(_dispatch_serial, ^{
NSLog(@"1------------ %@",[NSThread currentThread]);
});
dispatch_async(_dispatch_serial, ^{
NSLog(@"2------------ %@",[NSThread currentThread]);
});
dispatch_async(_dispatch_serial, ^{
NSLog(@"3------------ %@",[NSThread currentThread]);
});
NSLog(@"4------------ %@",[NSThread currentThread]);
}
列印的資料
2017-08-31 14:25:02.175 SYGCDStudy[8925:209538] 1------------ <NSThread: 0x600000267000>{number = 3, name = (null)}
2017-08-31 14:25:02.175 SYGCDStudy[8925:209484] 4------------ <NSThread: 0x60800007ca80>{number = 1, name = main}
2017-08-31 14:25:02.175 SYGCDStudy[8925:209538] 2------------ <NSThread: 0x600000267000>{number = 3, name = (null)}
2017-08-31 14:25:02.175 SYGCDStudy[8925:209538] 3------------ <NSThread: 0x600000267000>{number = 3, name = (null)}
先列印了4,然後順序在子執行緒中列印1,2,3。說明非同步執行具有開闢新執行緒的能力,並且序列佇列必須等到前一個任務執行完才能開始執行下一個任務,同時,非同步執行會使內部函式率先返回,不會與正在執行的外部函式發生死鎖。
並行同步佇列
//並行同步佇列
-(void)concurrentAndSynchronize{
dispatch_sync(_dispatch_concurrent, ^{
NSLog(@"1------------ %@",[NSThread currentThread]);
});
dispatch_sync(_dispatch_concurrent, ^{
NSLog(@"2------------ %@",[NSThread currentThread]);
});
dispatch_sync(_dispatch_concurrent, ^{
NSLog(@"3------------ %@",[NSThread currentThread]);
});
NSLog(@"4------------ %@",[NSThread currentThread]);
}
列印的資料
2017-08-31 14:30:10.572 SYGCDStudy[8953:213767] 1------------ <NSThread: 0x60800007c180>{number = 1, name = main}
2017-08-31 14:30:10.572 SYGCDStudy[8953:213767] 2------------ <NSThread: 0x60800007c180>{number = 1, name = main}
2017-08-31 14:30:10.573 SYGCDStudy[8953:213767] 3------------ <NSThread: 0x60800007c180>{number = 1, name = main}
2017-08-31 14:30:10.573 SYGCDStudy[8953:213767] 4------------ <NSThread: 0x60800007c180>{number = 1, name = main}
未開啟新的執行緒執行任務,並且Block函式執行完成後dispatch函式才會返回,才能繼續向下執行,所以我們看到的結果是順序列印的。
並行非同步佇列
//並行非同步佇列
-(void)concurrentAndASynchronize{
dispatch_async(_dispatch_concurrent, ^{
NSLog(@"1------------ %@",[NSThread currentThread]);
});
dispatch_async(_dispatch_concurrent, ^{
NSLog(@"2------------ %@",[NSThread currentThread]);
});
dispatch_async(_dispatch_concurrent, ^{
NSLog(@"3------------ %@",[NSThread currentThread]);
});
NSLog(@"4------------ %@",[NSThread currentThread]);
}
列印的資料
2017-08-31 14:34:08.966 SYGCDStudy[9008:220555] 3------------ <NSThread: 0x608000079380>{number = 5, name = (null)}
2017-08-31 14:34:08.966 SYGCDStudy[9008:220478] 4------------ <NSThread: 0x60000006da80>{number = 1, name = main}
2017-08-31 14:34:08.966 SYGCDStudy[9008:220557] 2------------ <NSThread: 0x600000077340>{number = 4, name = (null)}
2017-08-31 14:34:08.966 SYGCDStudy[9008:220554] 1------------ <NSThread: 0x608000079040>{number = 3, name = (null)}
開闢了多個執行緒,觸發任務的時機是順序的,但是我們看到完成任務的時間卻是隨機的,這取決於CPU對於不同執行緒的排程分配,但是,執行緒不是無條件無限開闢的,當任務量足夠大時,執行緒是會重複利用的。
3,其他一些常用的gcd方法
dispatch_once ,只執行一次的方法
//只執行一次
- (IBAction)carryOutOne:(id)sender {
static dispatch_once_t oneDispatch;
dispatch_once(&oneDispatch, ^{
NSLog(@"這個方法只會執行一次");
});
}
無論調起幾次這個方法,列印只會進行一次
dispatch_apply ,重複執行, 如果任務佇列是並行佇列,重複執行的任務會併發執行,如果任務佇列為序列佇列,則任務會順序執行,需要注意的是,該函式為同步函式,要防止執行緒阻塞和死鎖
//重複執行
- (IBAction)recurButton:(id)sender {
dispatch_apply(5, _dispatch_serial, ^(size_t i) {
NSLog(@"重複執行的次數。 %ld",i);
});
}
dispatch_after,延時執行,其中引數dispatch_time_t代表延時時長,dispatch_queue_t代表使用哪個佇列。如果佇列是主佇列,那麼任務在主執行緒執行,如果佇列為全域性佇列或者自己建立的佇列,那麼任務在子執行緒執行
//延時執行
- (IBAction)afterButton:(id)sender {
NSLog(@"延時三秒執行主執行緒--- 開始時間。%@",[NSDate date]);
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
dispatch_after(time, dispatch_get_main_queue(), ^{
NSLog(@"延時三秒執行主執行緒。%@",[NSDate date]);
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"延時五秒執行主執行緒。%@",[NSDate date]);
});
}
dispatch_group_async ,組佇列 。dispatch_group_notify,接收組佇列完成後執行的佇列。當加入到佇列組中的所有任務執行完成之後,會呼叫dispatch_group_notify函式通知任務全部完成
//分組完成
- (IBAction)groupButton:(id)sender {
dispatch_group_t groupDispatch = dispatch_group_create();
__block NSInteger index_1 = 0;
__block NSInteger index_2 = 0;
dispatch_group_async(groupDispatch, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_apply(10000, _dispatch_serial, ^(size_t i) {
index_1 = index_1 + i;
});
});
dispatch_group_async(groupDispatch, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_apply(2000, _dispatch_serial, ^(size_t i) {
index_2 = index_2 + i;
});
});
dispatch_group_notify(groupDispatch, dispatch_get_main_queue(), ^{
NSLog(@"這時候的 %ld,%ld",index_1,index_2);
});
}
該文章練習的demo地址:demo
相關文章
- iOS KVC學習記錄iOS
- iOS KVO學習記錄iOS
- iOS @property及其關鍵字學習記錄iOS
- GCD 學習總結GC
- 學習GCD歷程GC
- 學習記錄
- iOS多執行緒之GCD、OperationQueue 對比和實踐記錄iOS執行緒GC
- iOS RunTime 學習記錄1_類和物件iOS物件
- 【每日學習記錄】使用錄影裝置記錄每天的學習
- 記錄學習PromisePromise
- windbg學習記錄
- Eureka學習記錄
- Mybatis學習記錄MyBatis
- socket學習記錄
- JQuery學習記錄jQuery
- larabbs 學習記錄
- Tableau學習記錄
- MySQL學習記錄MySql
- Elasticsearch學習記錄Elasticsearch
- swift學習記錄Swift
- jQuery 學習記錄jQuery
- RAC 學習記錄
- RMAN學習記錄
- RAC學習記錄
- activiti學習記錄
- 學習記錄APPAPP
- langchain學習記錄LangChain
- JAVA學習記錄Java
- Docker學習記錄Docker
- 【記錄】MySQL 學習筆記MySql筆記
- [記錄] MySQL 學習筆記MySql筆記
- iOS GCD吹水iOSGC
- Flutter學習記錄(一)Dart學習FlutterDart
- iOS Block學習筆記iOSBloC筆記
- iOS Runloop學習筆記iOSOOP筆記
- Vue 學習記錄四Vue
- Vue 學習記錄三Vue
- Vue 學習記錄一Vue