国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > iOS > 正文

IOS中多線程編程的方法有哪些

2020-02-19 15:56:53
字體:
供稿:網(wǎng)友

本篇文章介紹了IOS中多線程編程的方法有哪些,下面小編給大家介紹詳細(xì)的解決步驟。

前言

在多線程簡介中,我已經(jīng)說明過了,為了提高界面的流暢度以及用戶體驗。我們務(wù)必要把耗時的操作放到別的線程中去執(zhí)行,千萬不要阻塞主線程。
iOS中有以下3種多線程編程方法:

NSThreadGrand Centeral Dispatch(GCD)NSOperation和NSOperationQueue

1.NSThread

這是最輕量級的多線程的方法,使用起來最直觀的多線程編程方法。但是因為需要自己管理線程的生命周期,線程同步。經(jīng)常使用NSThread進(jìn)行調(diào)試,在實際項目中不推薦使用。

//獲取當(dāng)前線程NSThread *current = [NSThread currentThread];//獲取主線程NSThread *main = [NSThread mainThread];NSLog(@"當(dāng)前線程 --- %@",current);NSLog(@"主線程 --- %@",main);

控制臺輸出結(jié)果:

2015-11-22 22:30:29.572 多線程demo[1289:2925847] 當(dāng)前線程 --- {number = 1, name = main}
2015-11-22 22:30:29.572 多線程demo[1289:2925847] 主線程 --- {number = 1, name = main}

從結(jié)果我們看出當(dāng)前的線程就是主線程,number相當(dāng)于線程的id,name是線程的名稱,主線程的number就是1

阻塞線程:

//阻塞線程3秒
[NSThread sleepForTimeInterval:3];
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:3]];

2.GCD(Grand Central Dispatch)

GCD是基于C語言底層API實現(xiàn)的一套多線程并發(fā)機制,非常的靈活方便,在實際的開發(fā)中使用很廣泛。
簡單來說CGD就是把操作放在隊列中去執(zhí)行。
你只需定義好操作和隊列就可以了,不需要直接控制線程的創(chuàng)建和銷毀,線程的生命周期由隊列來管理。

隊列:負(fù)責(zé)操作的調(diào)度和執(zhí)行,有先進(jìn)先出(FIFO)的特點。也就是說先加入隊列的操作先執(zhí)行,后加入的后執(zhí)行。

隊列有兩種:

串行隊列:

隊列中的操作只會按順序執(zhí)行,你可以想象成單窗口排隊。


并行隊列:

隊列中的操作可能會并發(fā)執(zhí)行,這取決與操作的類型,你可以想象成多窗口排隊。

?

//創(chuàng)建串行隊列
dispatch_queue_t q = dispatch_queue_create("my_serial_queue", DISPATCH_QUEUE_SERIAL);
//創(chuàng)建并行隊列
dispatch_queue_t q = dispatch_queue_create("my_concurrent_queue", DISPATCH_QUEUE_CONCURRENT);


my_serial_queue和my_concurrent_queue是隊列的名字標(biāo)簽,為了與其他的隊列區(qū)分,在一個項目里面必須是唯一的。
DISPATCH_QUEUE_SERIAL表示串行隊列
DISPATCH_QUEUE_CONCURRENT表示并行隊列

?

操作同樣也分兩種類型:
同步操作:只會按順序執(zhí)行,執(zhí)行順序是確定的。
異步操作:在串行隊列中執(zhí)行順序確定,在并行隊列中執(zhí)行順序不確定

使用block來定義操作要執(zhí)行的代碼,q是已經(jīng)定義好的,操作要加入的隊列

//定義同步操作dispatch_sync(q, ^{  //要執(zhí)行的代碼  });//定義異步操作dispatch_async(q, ^{  //要執(zhí)行的代碼   });

下面我們看一下同步,異步操作加入到串行和并行隊列里面,執(zhí)行的順序和特點:
1.同步操作不管加入到何種隊列,只會在主線程按順序執(zhí)行

dispatch_queue_t q_serial = dispatch_queue_create("my_serial_queue", DISPATCH_QUEUE_SERIAL);dispatch_queue_t q_concurrent = dispatch_queue_create("my_concurrent_queue", DISPATCH_QUEUE_CONCURRENT);for (int i = 0; i 

下面是控制臺輸出結(jié)果:

2015-11-23 00:40:36.862 01.GCD演練[1952:3613752] 串行隊列里的同步任務(wù) {number = 1, name = main} 0
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 串行隊列里的同步任務(wù) {number = 1, name = main} 1
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 串行隊列里的同步任務(wù) {number = 1, name = main} 2
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 串行隊列里的同步任務(wù) {number = 1, name = main} 3
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 串行隊列里的同步任務(wù) {number = 1, name = main} 4
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 并行隊列里的同步任務(wù) {number = 1, name = main} 0
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 并行隊列里的同步任務(wù) {number = 1, name = main} 1
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 并行隊列里的同步任務(wù) {number = 1, name = main} 2
2015-11-23 00:40:36.864 01.GCD演練[1952:3613752] 并行隊列里的同步任務(wù) {number = 1, name = main} 3
2015-11-23 00:40:36.864 01.GCD演練[1952:3613752] 并行隊列里的同步任務(wù) {number = 1, name = main} 4

2.異步操作只在非主線程的線程執(zhí)行,在串行隊列中異步操作會在新建的線程中按順序執(zhí)行。

?

??? dispatch_queue_t q_serial = dispatch_queue_create("my_serial_queue", DISPATCH_QUEUE_SERIAL);
??? for(int i = 0; i ??????? dispatch_async(q_serial, ^{
??????????? NSLog(@"串行隊列 -- 異步任務(wù) %@ %d", [NSThread currentThread], i);
??????? });
??? }

?

?

?

因為是異步操作,所以會新建一個線程。又因為加入到串行隊列中,所以所有的操作只會按順序執(zhí)行。

2015-11-23 01:03:22.372 01.GCD演練[2081:3627139] 串行隊列 -- 異步任務(wù) {number = 2, name = (null)} 0
2015-11-23 01:03:23.373 01.GCD演練[2081:3627139] 串行隊列 -- 異步任務(wù) {number = 2, name = (null)} 1
2015-11-23 01:03:24.374 01.GCD演練[2081:3627139] 串行隊列 -- 異步任務(wù) {number = 2, name = (null)} 2
2015-11-23 01:03:25.375 01.GCD演練[2081:3627139] 串行隊列 -- 異步任務(wù) {number = 2, name = (null)} 3
2015-11-23 01:03:26.376 01.GCD演練[2081:3627139] 串行隊列 -- 異步任務(wù) {number = 2, name = (null)} 4

3.異步操作,并行隊列

?

??? dispatch_queue_t q_concurrent = dispatch_queue_create("my_concurrent_queue", DISPATCH_QUEUE_CONCURRENT);
??? for(int i = 0; i ??????? dispatch_async(q_concurrent, ^{
??????????? NSLog(@"并行隊列 -- 異步任務(wù) %@ %d", [NSThread currentThread], i);
??????? });
??? }

?

?

?

理論上并行隊列會給每一個異步操作新建線程,然后讓所有的任務(wù)并發(fā)執(zhí)行。但是實際上系統(tǒng)能創(chuàng)建的線程數(shù)量是有限的,當(dāng)創(chuàng)建的線程達(dá)到最大線程數(shù)以后,后面的異步操作就需要等待前面的操作執(zhí)行完畢才能得到執(zhí)行。哪個線程操作執(zhí)行完畢,就把等待的異步任務(wù)安排到哪個線程。直到所有的操作執(zhí)行完畢。
你可以把上述代碼的循環(huán)次數(shù)改成5000就可以觀察到此現(xiàn)象。
2015-11-23 01:14:15.282 01.GCD演練[2165:3634728] 并行隊列 -- 異步任務(wù) {number = 4, name = (null)} 3
2015-11-23 01:14:15.282 01.GCD演練[2165:3634724] 并行隊列 -- 異步任務(wù) {number = 3, name = (null)} 0
2015-11-23 01:14:15.282 01.GCD演練[2165:3634726] 并行隊列 -- 異步任務(wù) {number = 5, name = (null)} 2
2015-11-23 01:14:15.282 01.GCD演練[2165:3634725] 并行隊列 -- 異步任務(wù) {number = 2, name = (null)} 1
2015-11-23 01:14:15.285 01.GCD演練[2165:3634729] 并行隊列 -- 異步任務(wù) {number = 6, name = (null)} 4

3.NSOperation & NSOperationQueue

雖然GCD的功能已經(jīng)很強大了,但是它使用的API依然是C語言的。在某些時候,在面向?qū)ο蟮膐bjective-c中使用起來非常的不方便和不安全。

所以蘋果公司把GCD中的操作抽象成NSOperation對象,把隊列抽象成NSOperationQueue對象。


抽象為NSOperation & NSOperationQueue以后的好處有一下幾點:

代碼風(fēng)格統(tǒng)一了,我們不用在面向?qū)ο蟮膐bjective-C中寫面對過程的C語言代碼了。
我們知道在GCD中操作的執(zhí)行代碼都是寫在匿名的block里面,那么我們很難做到給操作設(shè)置依賴關(guān)系以及取消操作。這些功能都已經(jīng)封裝到NSOperation對象里面了。^-^
NSOperationQueue對象比GCD中隊列更加的強大和靈活,比如:設(shè)置并發(fā)操作數(shù)量,取消隊列中所有操作。
NSOperation分為NSInvocationOperation和NSBlockOperation

NSInvocationOperation的使用

//首先定義一個NSOperationQueue對象NSOperationQueue *queue = [[NSOperationQueue alloc] init];NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationAction:) object:@"這里可以穿參數(shù)"];[queue addOperation:op];//把操作加入隊列中即開始執(zhí)行- (void)operationAction:(id)obj{  NSLog(@"%@ - obj : %@", [NSThread currentThread], obj);}

輸出為:

2015-11-23 02:55:19.067 多線程demo[2604:3686934] {number = 2, name = (null)} - obj : 這里可以穿參數(shù)
NSBlockOperation的使用

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
??? [self operationAction:@"這是NSBlockOperation"];
}];
[queue addOperation:op];
輸出為:

2015-11-23 02:56:11.812 多線程demo[2617:3687872] {number = 2, name = (null)} - obj : 這是NSBlockOperation
設(shè)置依賴關(guān)系(執(zhí)行順序)

??? NSOperationQueue *queue = [[NSOperationQueue alloc] init];
??? NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationAction:) object:@"op1"];
??? NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationAction:) object:@"op2"];
??? //op2在op1之后執(zhí)行
??? [op2 addDependency:op1];//這里需要注意,一定要在addOperation之前設(shè)置依賴關(guān)系
???
??? [queue addOperation:op1];
??? [queue addOperation:op2];
輸出為:

2015-11-23 02:57:40.283 多線程demo[2661:3689737] {number = 2, name = (null)} - obj : op1
2015-11-23 02:57:40.284 多線程demo[2661:3689737] {number = 2, name = (null)} - obj : op2

沒有設(shè)置依賴關(guān)系的輸出:

2015-11-23 03:00:45.939 多線程demo[2709:3692307] {number = 2, name = (null)} - obj : op2
2015-11-23 03:00:45.939 多線程demo[2709:3692308] {number = 3, name = (null)} - obj : op1

到這里你應(yīng)該發(fā)現(xiàn)了,在NSOperation & NSOperationQueue中,我們不需要再像GCD那樣定義操作的類型和隊列的類型和控制操作的執(zhí)行順序了,你只需要直接設(shè)定操作的執(zhí)行順序就可以了。

以上所述就是IOS中多線程編程的方法有哪些的介紹,希望大家能夠喜歡,更多內(nèi)容請繼續(xù)關(guān)注武林技術(shù)頻道網(wǎng)站!

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 阜新市| 福泉市| 乐亭县| 广灵县| 南陵县| 桐柏县| 马鞍山市| 琼结县| 积石山| 调兵山市| 天津市| 成都市| 桃源县| 庆安县| 缙云县| 钟祥市| 神农架林区| 拜泉县| 灵山县| 库伦旗| 宁陵县| 东宁县| 宣恩县| 广东省| 松阳县| 黔江区| 介休市| 巴林右旗| 离岛区| 蓬安县| 绍兴市| 焦作市| 莒南县| 抚宁县| 饶阳县| 吉安市| 亚东县| 辽中县| 汉中市| 雅安市| 铜鼓县|