亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

IOS多線程編程的3種實現方法

2020-07-26 03:31:48
字體:
來源:轉載
供稿:網友

前言

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

NSThreadGrand Centeral Dispatch(GCD)NSOperation和NSOperationQueue

1.NSThread

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

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

控制臺輸出結果:

2015-11-22 22:30:29.572 多線程demo[1289:2925847] 當前線程 --- <NSThread: 0x7fc0e1401dc0>{number = 1, name = main}
2015-11-22 22:30:29.572 多線程demo[1289:2925847] 主線程 --- <NSThread: 0x7fc0e1401dc0>{number = 1, name = main}
從結果我們看出當前的線程就是主線程,number相當于線程的id,name是線程的名稱,主線程的number就是1

阻塞線程:

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

2.GCD(Grand Central Dispatch)

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

隊列:負責操作的調度和執行,有先進先出(FIFO)的特點。也就是說先加入隊列的操作先執行,后加入的后執行。

隊列有兩種:

串行隊列:

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


并行隊列:

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

復制代碼 代碼如下:
//創建串行隊列
dispatch_queue_t q = dispatch_queue_create("my_serial_queue", DISPATCH_QUEUE_SERIAL);
//創建并行隊列
dispatch_queue_t q = dispatch_queue_create("my_concurrent_queue", DISPATCH_QUEUE_CONCURRENT);

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

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

使用block來定義操作要執行的代碼,q是已經定義好的,操作要加入的隊列

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

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

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 < 5; ++i) {  dispatch_sync(q_serial, ^{    NSLog(@"串行隊列里的同步任務 %@ %d", [NSThread currentThread], i);  });}for (int i = 0; i < 5; ++i) {  dispatch_sync(q_concurrent, ^{    NSLog(@"并行隊列里的同步任務 %@ %d", [NSThread currentThread], i);  });}

下面是控制臺輸出結果:

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

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

復制代碼 代碼如下:
    dispatch_queue_t q_serial = dispatch_queue_create("my_serial_queue", DISPATCH_QUEUE_SERIAL);
    for(int i = 0; i < 5; ++i){
        dispatch_async(q_serial, ^{
            NSLog(@"串行隊列 -- 異步任務 %@ %d", [NSThread currentThread], i);
        });
    }

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

2015-11-23 01:03:22.372 01.GCD演練[2081:3627139] 串行隊列 -- 異步任務 <NSThread: 0x7fb593d42f50>{number = 2, name = (null)} 0
2015-11-23 01:03:23.373 01.GCD演練[2081:3627139] 串行隊列 -- 異步任務 <NSThread: 0x7fb593d42f50>{number = 2, name = (null)} 1
2015-11-23 01:03:24.374 01.GCD演練[2081:3627139] 串行隊列 -- 異步任務 <NSThread: 0x7fb593d42f50>{number = 2, name = (null)} 2
2015-11-23 01:03:25.375 01.GCD演練[2081:3627139] 串行隊列 -- 異步任務 <NSThread: 0x7fb593d42f50>{number = 2, name = (null)} 3
2015-11-23 01:03:26.376 01.GCD演練[2081:3627139] 串行隊列 -- 異步任務 <NSThread: 0x7fb593d42f50>{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 < 5; ++i){
        dispatch_async(q_concurrent, ^{
            NSLog(@"并行隊列 -- 異步任務 %@ %d", [NSThread currentThread], i);
        });
    }

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

3.NSOperation & NSOperationQueue

雖然GCD的功能已經很強大了,但是它使用的API依然是C語言的。在某些時候,在面向對象的objective-c中使用起來非常的不方便和不安全。

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


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

代碼風格統一了,我們不用在面向對象的objective-C中寫面對過程的C語言代碼了。
我們知道在GCD中操作的執行代碼都是寫在匿名的block里面,那么我們很難做到給操作設置依賴關系以及取消操作。這些功能都已經封裝到NSOperation對象里面了。^-^
NSOperationQueue對象比GCD中隊列更加的強大和靈活,比如:設置并發操作數量,取消隊列中所有操作。
NSOperation分為NSInvocationOperation和NSBlockOperation

NSInvocationOperation的使用

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

輸出為:

2015-11-23 02:55:19.067 多線程demo[2604:3686934] <NSThread: 0x7f9dfa443510>{number = 2, name = (null)} - obj : 這里可以穿參數
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] <NSThread: 0x7fa983f10a50>{number = 2, name = (null)} - obj : 這是NSBlockOperation
設置依賴關系(執行順序)

    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之后執行
    [op2 addDependency:op1];//這里需要注意,一定要在addOperation之前設置依賴關系
   
    [queue addOperation:op1];
    [queue addOperation:op2];
輸出為:

2015-11-23 02:57:40.283 多線程demo[2661:3689737] <NSThread: 0x7fb663e132d0>{number = 2, name = (null)} - obj : op1
2015-11-23 02:57:40.284 多線程demo[2661:3689737] <NSThread: 0x7fb663e132d0>{number = 2, name = (null)} - obj : op2
沒有設置依賴關系的輸出:

2015-11-23 03:00:45.939 多線程demo[2709:3692307] <NSThread: 0x7fe951d0d8a0>{number = 2, name = (null)} - obj : op2
2015-11-23 03:00:45.939 多線程demo[2709:3692308] <NSThread: 0x7fe951c24720>{number = 3, name = (null)} - obj : op1
到這里你應該發現了,在NSOperation & NSOperationQueue中,我們不需要再像GCD那樣定義操作的類型和隊列的類型和控制操作的執行順序了,你只需要直接設定操作的執行順序就可以了。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91天堂在线视频| 亚洲视频电影图片偷拍一区| 日韩av123| 欧美刺激性大交免费视频| 欧美在线一级va免费观看| 亚洲尤物视频网| 国产精品日韩久久久久| xxx成人少妇69| 精品无人国产偷自产在线| 国产有码一区二区| 欧美激情性做爰免费视频| www.亚洲免费视频| 在线观看国产精品91| 日韩欧美在线免费观看| 精品亚洲夜色av98在线观看| 亚洲成人网在线观看| 国产精品美女呻吟| 国产精品视频在线观看| 精品久久久久久久久国产字幕| 精品成人在线视频| 丝袜亚洲另类欧美重口| 91在线国产电影| 超碰日本道色综合久久综合| 国产69精品久久久久久| 91色中文字幕| 欧美激情欧美激情在线五月| 精品亚洲永久免费精品| 国产午夜精品一区理论片飘花| 久久精品视频在线播放| 欧美精品18videos性欧| 欧美激情2020午夜免费观看| 91精品国产91久久久久久吃药| 国产精品观看在线亚洲人成网| 色综合91久久精品中文字幕| 欧美成人免费一级人片100| 国产精品视频久久| 国产成人激情小视频| 久久国产精品久久精品| 国产亚洲成av人片在线观看桃| 欧美二区在线播放| 亚洲激情视频网站| 亚洲第一色在线| 91久久嫩草影院一区二区| 国产精国产精品| 久久中文字幕国产| 57pao成人永久免费视频| 在线播放亚洲激情| 精品亚洲一区二区三区四区五区| 欧美中文在线观看国产| 欧美丝袜一区二区| 久久亚洲精品国产亚洲老地址| 亚洲天堂第二页| 日本亚洲欧美成人| 一个人www欧美| 亚洲福利视频网站| 亚洲精品自拍第一页| 主播福利视频一区| 中文字幕av一区二区三区谷原希美| 91老司机在线| 中文字幕少妇一区二区三区| 欧美激情视频在线| 欧美最猛性xxxxx(亚洲精品)| 97精品免费视频| 最新亚洲国产精品| 久久夜色精品国产欧美乱| 91免费的视频在线播放| 国产精品69精品一区二区三区| 国产91露脸中文字幕在线| 欧美成人亚洲成人日韩成人| 97欧美精品一区二区三区| 日韩在线www| 亚洲女人天堂成人av在线| 欧美午夜www高清视频| 国模吧一区二区三区| 精品视频—区二区三区免费| 亚洲国产成人精品电影| 国产aaa精品| 国产精品视频26uuu| 中文字幕日韩综合av| 日韩一区二区三区xxxx| 萌白酱国产一区二区| 国产精品免费久久久久久| 亚洲精品国产成人| 久久精品视频在线| 欧美精品免费在线| 日本精品一区二区三区在线播放视频| 久久全球大尺度高清视频| 91黑丝在线观看| 中文字幕日韩欧美| 国产精品扒开腿做| 91av在线视频观看| 亚洲天堂男人天堂女人天堂| 久久99久久99精品中文字幕| 性亚洲最疯狂xxxx高清| 亚洲第一福利在线观看| 这里只有精品在线观看| 日韩av在线网| 欧美xxxwww| 国产欧美一区二区白浆黑人| 亚洲另类图片色| 国产精品美女www爽爽爽视频| 日韩精品免费在线播放| 欧美高清视频在线| 3344国产精品免费看| 欧美国产一区二区三区| 国产精品久久久久久影视| 96pao国产成视频永久免费| 亚洲欧洲在线免费| 91久久精品日日躁夜夜躁国产| 日韩在线观看免费全| 亚洲网站视频福利| 亚洲三级黄色在线观看| 精品久久久国产| 久久精品免费电影| 国产主播喷水一区二区| 美女精品视频一区| 中文字幕久久精品| 国产精品成熟老女人| 亚洲精品国产精品久久清纯直播| 中文字幕九色91在线| 精品久久在线播放| 亚洲国产第一页| 欧美福利视频在线| 国产精品18久久久久久麻辣| 国产亚洲精品va在线观看| 欧洲s码亚洲m码精品一区| 亚洲第一国产精品| 精品成人在线视频| 日韩av片电影专区| 亚洲国产精品久久久久秋霞不卡| 亚洲最大成人网色| 亚洲一区二区中文| 日韩成人免费视频| 欧美精品免费在线观看| 久久91精品国产91久久久| 一本色道久久综合狠狠躁篇的优点| 午夜精品久久久久久久久久久久久| 欧美丝袜美女中出在线| 中日韩美女免费视频网址在线观看| 国产精品成人va在线观看| 欧美在线一区二区视频| 91精品久久久久久| 国产福利视频一区二区| 人体精品一二三区| 日本免费久久高清视频| 亚洲欧美日韩一区二区三区在线| 亚洲国产成人在线视频| 亚洲桃花岛网站| 久久91亚洲精品中文字幕奶水| 91免费视频国产| 久久久国产91| 亚洲伊人久久大香线蕉av| 久久中文字幕视频| 欧美成年人网站| 久久视频免费在线播放| 欧美黑人性生活视频| 午夜精品在线视频| 色中色综合影院手机版在线观看| 欧美激情视频给我| 欧美日韩亚洲系列| 亚洲一区国产精品| 久久久久国产精品免费| 国产欧美精品一区二区三区-老狼| 精品在线小视频|