oc中多線程

關于多線程,在編程中那是必不可少的,現在我們就好好梳理一下多線程.

在 iOS 中其實目前主要有3套多線程方案,他們分別是:

NSThread

GCD

NSOperation & NSOperationQueue


NSThread

NSThread是經過蘋果封裝后的,并且完全面向對象的。所以你可以直接操控線程對象,非常直觀和方便。

它的生命周期還是需要我們手動管理,所以并不推薦使用

//多線程處理

-(void)manyThreadHandle

{

//方法1

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(makerun:) object:@"1"];

// 啟動

[thread start];

//方法2? 不用手動啟動 自動啟動

[NSThread detachNewThreadWithBlock:^{

NSLog(@"--方法2");

}];

//方法3? 不用手動啟動自動啟動

[NSThread detachNewThreadSelector:@selector(makerun:) toTarget:self withObject:@"2"];

}

-(void)makerun:(NSThread*)thred

{

NSLog(@"多線程--%@",thred);

}

2017-08-30 16:01:24.863 runtimeTest[6579:165898] --方法2

2017-08-30 16:01:24.864 runtimeTest[6579:165897] 多線程--1

2017-08-30 16:01:24.864 runtimeTest[6579:165899] 多線程--2

在NSThread 中海油很多方法和屬性

//取消線程

- (void)cancel;

//啟動線程

- (void)start;

//判斷某個線程的狀態的屬性

@property (readonly, getter=isExecuting) BOOL executing;

@property (readonly, getter=isFinished) BOOL finished;

@property (readonly, getter=isCancelled) BOOL cancelled;

//設置和獲取線程名字

-(void)setName:(NSString *)n;

-(NSString *)name;

//獲取當前線程信息

+ (NSThread *)currentThread;

//獲取主線程信息

+ (NSThread *)mainThread;

//使當前線程暫停一段時間,或者暫停到某個時刻

+ (void)sleepForTimeInterval:(NSTimeInterval)time;

+ (void)sleepUntilDate:(NSDate *)date;


GCD 方法

GCD 這個名字是不是很霸氣 ,天朝人都懂得.其實指的是Grand Central Dispatch(GCD)

GCD會自動合理地利用更多的CPU內核(比如雙核、四核),最重要的是它會自動管理線程的生命周期(創建線程、調度任務、銷毀線程),完全不需要我們管理,我們只需要告訴干什么就行。同時它使用的也是c語言,不過由于使用了 Block(Swift里叫做閉包),使得使用起來更加方便,而且靈活。這個方法比較實用簡便,強烈推薦.

在GCD中,加入了兩個非常重要的概念:任務隊列

任務

任務:即操作,你想要干什么,說白了就是一段代碼,在 GCD 中就是一個 Block,所以添加任務十分方便。任務有兩種執行方式:同步執行異步執行,主要區別在于會不會阻塞當前線程,直到Block中的任務執行完畢!

同步執行:阻塞當前線程,不會開辟新的線程

異步執行:不會阻塞當前線,程會開辟新的線程

隊列:用于存放任務。一共有兩種隊列,串行隊列并行隊列。

放到串行隊列的任務,GCD 會FIFO(先進先出)地取出來一個,執行一個,然后取下一個,這樣一個一個的執行。簡單說串行 就是單行車道 ,所有的車(任務)都只能按順序走

放到并行隊列的任務,GCD 也會FIFO的取出來,但不同的是,它取出來一個就會放到別的線程,然后再取出來一個又放到另一個的線程。這樣由于取的動作很快,忽略不計,看起來,所有的任務都是一起執行的。簡單說并行 就是多條車道 ,所有的車(任務)都可以在對應車道上走,和隔壁車道沒什么影響

主隊列? 任何需要刷新 UI 的工作都要在主隊列執行

dispatch_queue_t queue = dispatch_get_main_queue();

自己創建隊列

//串行隊列

dispatch_queue_t queue = dispatch_queue_create("tk22.bournes.testQueue", NULL);

dispatch_queue_t queue = dispatch_queue_create("tk22.bournes.testQueue", DISPATCH_QUEUE_SERIAL);

//并行隊列

dispatch_queue_t queue = dispatch_queue_create("tk22.bournes.testQueue", DISPATCH_QUEUE_CONCURRENT);

//全局并行隊列

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

隊列組

隊列組可以將很多隊列添加到一個組里,這樣做的好處是,當這個組里所有的任務都執行完了,隊列組會通過一個方法通知我們。

//1.創建隊列組

dispatch_group_t group = dispatch_group_create();

//2.創建隊列

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

//多次使用隊列組的方法執行任務, 只有異步方法

//執行3次循環

dispatch_group_async(group, queue, ^{

for (NSInteger i = 0; i < 3; i++) {

NSLog(@"group-01 - %@", [NSThread currentThread]);

}

});

//主隊列執行8次循環

dispatch_group_async(group, dispatch_get_main_queue(), ^{

for (NSInteger i = 0; i < 8; i++) {

NSLog(@"group-02 - %@", [NSThread currentThread]);

}

});

//執行10次循環

dispatch_group_async(group, queue, ^{

for (NSInteger i = 0; i < 10; i++) {

NSLog(@"group-03 - %@", [NSThread currentThread]);

}

});

//4.都完成后會自動通知

dispatch_group_notify(group, dispatch_get_main_queue(), ^{

NSLog(@"完成 - %@", [NSThread currentThread]);

});

//運行結果

2017-08-30 16:21:36.201 runtimeTest[6843:174540] group-01 -{number = 3, name = (null)} ? ? ? ? ?2017-08-30 16:21:36.201 runtimeTest[6843:174555] group-03 -{number = 4, name = (null)} ? ? ? ? 2017-08-30 16:21:36.202 runtimeTest[6843:174555] group-03 -{number = 4, name = (null)} ? ? ? ?2017-08-30 16:21:36.202 runtimeTest[6843:174540] group-01 -{number = 3, name = (null)} ? ? ? ? 2017-08-30 16:21:36.202 runtimeTest[6843:174555] group-03 -{number = 4, name = (null)} ? ? ? ?2017-08-30 16:21:36.202 runtimeTest[6843:174540] group-01 -{number = 3, name = (null)} ? ? ? ? 2017-08-30 16:21:36.202 runtimeTest[6843:174555] group-03 -{number = 4, name = (null)} ? ? ? ?2017-08-30 16:21:36.202 runtimeTest[6843:174555] group-03 -{number = 4, name = (null)} ? ? ? ?2017-08-30 16:21:36.202 runtimeTest[6843:174555] group-03 -{number = 4, name = (null)} ? ? ? ?2017-08-30 16:21:36.203 runtimeTest[6843:174555] group-03 -{number = 4, name = (null)} ? ? ? ?2017-08-30 16:21:36.203 runtimeTest[6843:174555] group-03 -{number = 4, name = (null)} ? ? ? ?2017-08-30 16:21:36.203 runtimeTest[6843:174555] group-03 -{number = 4, name = (null)} ? ? ? ?2017-08-30 16:21:36.203 runtimeTest[6843:174555] group-03 -{number = 4, name = (null)} ? ? ? ?2017-08-30 16:21:36.206 runtimeTest[6843:174502] group-02 -{number = 1, name = main} ? ? ? ? 2017-08-30 16:21:36.207 runtimeTest[6843:174502] group-02 -{number = 1, name = main} ? ? ? ? ?2017-08-30 16:21:36.207 runtimeTest[6843:174502] group-02 -{number = 1, name = main} ? ? ? ? ?2017-08-30 16:21:36.207 runtimeTest[6843:174502] group-02 -{number = 1, name = main} ? ? ? ? ?2017-08-30 16:21:36.207 runtimeTest[6843:174502] group-02 -{number = 1, name = main} ? ? ? ? ?2017-08-30 16:21:36.208 runtimeTest[6843:174502] group-02 -{number = 1, name = main} ? ? ? ? 2017-08-30 16:21:36.208 runtimeTest[6843:174502] group-02 -{number = 1, name = main} ? ? ? ? 2017-08-30 16:21:36.208 runtimeTest[6843:174502] group-02 -{number = 1, name = main} ? ? ? ? ?2017-08-30 16:21:36.209 runtimeTest[6843:174502] 完成 -{number = 1, name = main}


NSOperation和NSOperationQueue

NSOperation 是蘋果公司對 GCD 的封裝,完全面向對象,所以使用起來更好理解,有很多和GCD比較類似

NSOperation 和 NSOperationQueue分別對應 GCD 的任務 和 隊列

NSOperation只是一個抽象類,所以不能封裝任務它有 2 個子類用于封裝任務。分別是:NSInvocationOperation和NSBlockOperation

當你新創建一個 Operation 后,需要手動的調用start方法來啟動任務,它會默認在當前隊列同步執行。當然你也可以在中途取消一個任務,只需要調用其cancel方法即可。


//1.創建NSInvocationOperation對象

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];

//2.開始執行

[operation start];

//1.創建NSBlockOperation對象

NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{

NSLog(@"%@", [NSThread currentThread]);

}];

//添加多個Block

for (NSInteger i = 0; i < 5; i++) {

[operation addExecutionBlock:^{

NSLog(@"第%ld次:%@", i, [NSThread currentThread]);

}];

}

//2.開始任務

[operation start];

2017-08-30 16:33:12.868 runtimeTest[7014:179819]{number = 1, name = main}

2017-08-30 16:33:12.869 runtimeTest[7014:179819] 第3次:{number = 1, name = main}

2017-08-30 16:33:12.869 runtimeTest[7014:179819] 第4次:{number = 1, name = main}

2017-08-30 16:33:12.868 runtimeTest[7014:179888] 第1次:{number = 4, name = (null)}

2017-08-30 16:33:12.868 runtimeTest[7014:179892] 第0次:{number = 3, name = (null)}

2017-08-30 16:33:12.869 runtimeTest[7014:179889] 第2次:{number = 5, name = (null)}

根據結果可以知道打印的順序是亂的 這個也符合我們異步的任務執行情況

//1.創建NSBlockOperation對象

NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{

NSLog(@"%@", [NSThread currentThread]);

}];

//2.開始任務

[operation start];

創建隊列

//主隊列

NSOperationQueue *queue = [NSOperationQueue mainQueue];

//1.創建一個其他隊列

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

//2.創建NSBlockOperation對象

NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{

NSLog(@"%@", [NSThread currentThread]);

}];

//3.添加多個Block

for (NSInteger i = 0; i < 2; i++) {

[operation addExecutionBlock:^{

NSLog(@"第%ld次:%@", i, [NSThread currentThread]);

}];

}

//4.隊列添加任務

[queue addOperation:operation];

2017-08-30 16:35:56.163 runtimeTest[7073:181494]{number = 3, name = (null)}

2017-08-30 16:35:56.163 runtimeTest[7073:181537] 第0次:{number = 4, name = (null)}

2017-08-30 16:35:56.163 runtimeTest[7073:181538] 第1次:{number = 5, name = (null)}

NSOperation有一個非常實用的功能,那就是添加依賴 和gcd中的隊列組管理有點類似.有點啰嗦了,就先介紹這些吧,以后有時間會更新.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 一、前言 上一篇文章iOS多線程淺匯-原理篇中整理了一些有關多線程的基本概念。本篇博文介紹的是iOS中常用的幾個多...
    nuclear閱讀 2,073評論 6 18
  • 在這篇文章中,我將為你整理一下 iOS 開發中幾種多線程方案,以及其使用方法和注意事項。當然也會給出幾種多線程的案...
    張戰威ican閱讀 615評論 0 0
  • 文章目錄GCD簡介任務和隊列GCD的使用步驟隊列的創建方法任務的創建方法GCD的基本使用并行隊列 + 同步執行并行...
    lusen_b閱讀 253評論 0 1
  • 一、前言 本篇博文介紹的是iOS中常用的幾個多線程技術: NSThread GCD NSOperation 由于a...
    和玨貓閱讀 588評論 0 1
  • 正常健康的嘴唇一般膚色紅潤而有光澤,干濕適度而有彈性。 2.嘴唇為紅色或深紅色、紫紅色 這是提示你的身體狀態火比較...
    微微小醫閱讀 331評論 0 0