iOS 多線程

參考資料:
iOS多線程
iOS GCD

多線程問題在iOS中目前有4套多線程方案秘蛔,他們分別是:

  • Pthreads
  • NSthread
  • GCD
  • NSOperation

Pthreads

這是一套在很多操作系統(tǒng)通用的多線程API呢袱,不過這是基于c語言的框架,在iOS實際開發(fā)中很少使用饱亿。

  1. 包含頭文件:
    #import <pthread.h>
  2. 創(chuàng)建線程,并執(zhí)行任務(wù):
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 創(chuàng)建一個新的線程并自動執(zhí)行
    pthread_t thread;
    pthread_create(&thread, NULL, pthreadStart, NULL);
}

void *pthreadStart() {
    NSLog(@"%@", [NSThread currentThread]);
    return NULL;
}
  1. 輸出打印:
    <NSThread: 0x6040002719c0>{number = 3, name = (null)}

NSthread

這套方案是蘋果封裝的多線程解決方案滩租。可以直接操控線程對象利朵。但是律想,它的生命周期還是需要我們手動管理,所以這套方案使用頻率不高绍弟,下面來看看它的一些用法技即。

  1. 創(chuàng)建線程并啟動
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadStart) object:nil];
[thread start];
  1. 創(chuàng)建線程并自動啟動
[NSThread detachNewThreadSelector:@selector(threadStart) toTarget:self withObject:nil];
  1. 使用NSObject的方法創(chuàng)建線程并自動啟動
[self performSelectorInBackground:@selector(threadStart) withObject:nil];
  1. 其他常用方法
//取消線程
- (void)cancel;

//啟動線程
- (void)start;

//判斷某個線程的狀態(tài)的屬性
@property (readonly, getter=isExecuting) BOOL executing;
@property (readonly, getter=isFinished) BOOL finished;
@property (readonly, getter=isCancelled) BOOL cancelled;

//設(shè)置和獲取線程名字
-(void)setName:(NSString *)n;
-(NSString *)name;

//獲取當(dāng)前線程信息
+ (NSThread *)currentThread;

//獲取主線程信息
+ (NSThread *)mainThread;

//使當(dāng)前線程暫停一段時間,或者暫停到某個時刻
+ (void)sleepForTimeInterval:(NSTimeInterval)time;
+ (void)sleepUntilDate:(NSDate *)date;

GCD

Grand Central Dispatch樟遣,它是蘋果為多核的并行運算提出的解決方案,所以會自動合理地利用更多的CPU內(nèi)核(比如雙核、四核)抽莱,最重要的是它會自動管理線程的生命周期(創(chuàng)建線程分瘦、調(diào)度任務(wù)、銷毀線程)瞻佛,完全不需要我們管理脱篙,我們只需要告訴干什么就行娇钱。同時它使用的也是 c語言,不過由于使用了Block(Swift里叫做閉包)绊困,使得使用起來更加方便文搂,而且靈活。

1. 任務(wù)和隊列

GCD中秤朗,加入了兩個非常重要的概念:任務(wù)隊列煤蹭。

  • 任務(wù):即操作,你想要干什么川梅,說白了就是一段代碼疯兼,在 GCD 中就是一個 Block,所以添加任務(wù)十分方便贫途。任務(wù)有兩種執(zhí)行方式: 同步執(zhí)行 和 異步執(zhí)行吧彪,他們之間的區(qū)別是 是否會創(chuàng)建新的線程

同步(sync) 和 異步(async) 的主要區(qū)別在于會不會阻塞當(dāng)前線程丢早,直到 Block 中的任務(wù)執(zhí)行完畢姨裸!
如果是 同步(sync) 操作,它會阻塞當(dāng)前線程并等待 Block 中的任務(wù)執(zhí)行完畢怨酝,然后當(dāng)前線程才會繼續(xù)往下運行傀缩。
如果是 異步(async)操作,當(dāng)前線程會直接往下執(zhí)行农猬,它不會阻塞當(dāng)前線程赡艰。

  • 隊列:用于存放任務(wù)。一共有兩種隊列斤葱, 串行隊列 和 并行隊列慷垮。
    串行隊列 中的任務(wù),GCD 會 FIFO(先進(jìn)先出) 地取出來一個揍堕,執(zhí)行一個料身,然后取下一個,這樣一個一個的執(zhí)行衩茸。
    并行隊列 中的任務(wù)芹血,GCD 也會 FIFO的取出來,但不同的是楞慈,它取出來一個就會放到別的線程幔烛,然后再取出來一個又放到另一個的線程。這樣由于取的動作很快囊蓝,忽略不計饿悬,看起來,所有的任務(wù)都是一起執(zhí)行的慎颗。不過需要注意乡恕,GCD 會根據(jù)系統(tǒng)資源控制并行的數(shù)量言询,所以如果任務(wù)很多,它并不會讓所有任務(wù)同時執(zhí)行傲宜。

2. 創(chuàng)建隊列

  • 主隊列:這是一個特殊的 串行隊列运杭。什么是主隊列,大家都知道吧函卒,它用于刷新 UI辆憔,任何需要刷新 UI 的工作都要在主隊列執(zhí)行,所以一般耗時的任務(wù)都要放到別的線程執(zhí)行报嵌。
//OBJECTIVE-C
dispatch_queue_t queue = ispatch_get_main_queue();
  • 自己創(chuàng)建的隊列:自己可以創(chuàng)建 串行隊列, 也可以創(chuàng)建 并行隊列虱咧。看下面的代碼(代碼已更新)锚国,它有兩個參數(shù)腕巡,第一個上面已經(jīng)說了,第二個才是最重要的血筑。
    第二個參數(shù)用來表示創(chuàng)建的隊列是串行的還是并行的绘沉,傳入 DISPATCH_QUEUE_SERIALNULL 表示創(chuàng)建串行隊列。傳入 DISPATCH_QUEUE_CONCURRENT 表示創(chuàng)建并行隊列豺总。
//串行隊列
dispatch_queue_t queue = dispatch_queue_create("tk.bourne.testQueue", NULL);
dispatch_queue_t queue = dispatch_queue_create("tk.bourne.testQueue", DISPATCH_QUEUE_SERIAL);
//并行隊列
dispatch_queue_t queue = dispatch_queue_create("tk.bourne.testQueue", DISPATCH_QUEUE_CONCURRENT);
  • 全局并行隊列:只要是并行任務(wù)一般都加入到這個隊列车伞。這是系統(tǒng)提供的一個并發(fā)隊列。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

3. 創(chuàng)建任務(wù)

  • 同步任務(wù):會阻塞當(dāng)前線程 (SYNC)
dispatch_sync(<#queue#>, ^{
    //code here
    NSLog(@"%@", [NSThread currentThread]);
});
  • 異步任務(wù):不會阻塞當(dāng)前線程 (ASYNC)
dispatch_async(<#queue#>, ^{
    //code here
    NSLog(@"%@", [NSThread currentThread]);
});

4. 隊列組

隊列組可以將很多隊列添加到一個組里喻喳,這樣做的好處是另玖,當(dāng)這個組里所有的任務(wù)都執(zhí)行完了,隊列組會通過一個方法通知我們表伦。下面是使用方法谦去,這是一個很實用的功能。

//1.創(chuàng)建隊列組
dispatch_group_t group = dispatch_group_create();
//2.創(chuàng)建隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

//3.多次使用隊列組的方法執(zhí)行任務(wù), 只有異步方法
//3.1.執(zhí)行3次循環(huán)
dispatch_group_async(group, queue, ^{
    for (NSInteger i = 0; i < 3; i++) {
        NSLog(@"group-01 - %@", [NSThread currentThread]);
    }
});

//3.2.主隊列執(zhí)行8次循環(huán)
dispatch_group_async(group, dispatch_get_main_queue(), ^{
    for (NSInteger i = 0; i < 8; i++) {
        NSLog(@"group-02 - %@", [NSThread currentThread]);
    }
});

//3.3.執(zhí)行5次循環(huán)
dispatch_group_async(group, queue, ^{
    for (NSInteger i = 0; i < 5; i++) {
        NSLog(@"group-03 - %@", [NSThread currentThread]);
    }
});

//4.都完成后會自動通知
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    NSLog(@"完成 - %@", [NSThread currentThread]);
});

5. 柵欄方法

  • 我們有時需要異步執(zhí)行兩組操作绑榴,而且第一組操作執(zhí)行完之后哪轿,才能開始執(zhí)行第二組操作盈魁。這樣我們就需要一個相當(dāng)于柵欄一樣的一個方法將兩組異步執(zhí)行的操作組給分割起來翔怎,當(dāng)然這里的操作組里可以包含一個或多個任務(wù)。這就需要用到dispatch_barrier_async方法在兩個操作組間形成柵欄杨耙。
dispatch_queue_t queue = dispatch_queue_create("12312312", DISPATCH_QUEUE_CONCURRENT);

dispatch_async(queue, ^{
    NSLog(@"----1-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
    NSLog(@"----2-----%@", [NSThread currentThread]);
});

dispatch_barrier_async(queue, ^{
    NSLog(@"----barrier-----%@", [NSThread currentThread]);
});

dispatch_async(queue, ^{
    NSLog(@"----3-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
    NSLog(@"----4-----%@", [NSThread currentThread]);
});

6. 延時執(zhí)行

  • 當(dāng)我們需要延遲執(zhí)行一段代碼時赤套,就需要用到GCD的dispatch_after方法。
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    // 2秒后異步執(zhí)行這里的代碼...
   NSLog(@"run-----");
});

7. 一次性代碼

  • 我們在創(chuàng)建單例珊膜、或者有整個程序運行過程中只執(zhí)行一次的代碼時容握,我們就用到了GCD的dispatch_once方法。使用dispatch_once函數(shù)能保證某段代碼在程序運行過程中只被執(zhí)行1次车柠。
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    // 只執(zhí)行1次的代碼(這里面默認(rèn)是線程安全的)
});

8. 快速迭代方法

  • 通常我們會用for循環(huán)遍歷剔氏,但是GCD給我們提供了快速迭代的方法dispatch_apply塑猖,使我們可以同時遍歷。比如說遍歷0~5這6個數(shù)字谈跛,for循環(huán)的做法是每次取出一個元素羊苟,逐個遍歷。dispatch_apply可以同時遍歷多個數(shù)字感憾。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_apply(6, queue, ^(size_t index) {
    NSLog(@"%zd------%@",index, [NSThread currentThread]);
});

NSOperation

NSOperation 是蘋果公司對 GCD 的封裝蜡励,完全面向?qū)ο螅允褂闷饋砀美斫狻?大家可以看到NSOperationNSOperationQueue分別對應(yīng) GCD 的任務(wù)隊列阻桅。操作步驟如下:

  1. 將要執(zhí)行的任務(wù)封裝到一個NSOperation對象中凉倚。
  2. 將此任務(wù)添加到一個NSOperationQueue對象中。

注:
NSOperation只是一個抽象類嫂沉,所以不能封裝任務(wù)稽寒。但它有 2 個子類用于封裝任務(wù)。分別是:NSInvocationOperationNSBlockOperation趟章。創(chuàng)建一個Operation后瓦胎,需要調(diào)用start方法來啟動任務(wù),它會 默認(rèn)在當(dāng)前隊列同步執(zhí)行尤揣。當(dāng)然你也可以在中途取消一個任務(wù)搔啊,只需要調(diào)用其cancel方法即可。

  • NSInvocationOperation:
//1.創(chuàng)建NSInvocationOperation對象
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];

//2.開始執(zhí)行
[operation start];
  • NSBlockOperation
//1.創(chuàng)建NSBlockOperation對象
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"%@", [NSThread currentThread]);
}];

//2.開始任務(wù)
[operation start];

NSBlockOperation默認(rèn)會在當(dāng)前線程執(zhí)行北戏。但它還有一個方法:addExecutionBlock:负芋,通過這個方法可以給Operation添加多個執(zhí)行 Block。這樣 Operation 中的任務(wù) 會并發(fā)執(zhí)行嗜愈,它會在主線程和其它的多個線程 執(zhí)行這些任務(wù)旧蛾。

NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"%@", [NSThread currentThread]);
}];

for (int i = 0; i < 5; i++) {
    [operation addExecutionBlock:^{
        NSLog(@"execution - %@", [NSThread currentThread]);
    }];
}

[operation start];

輸出打印:

<NSThread: 0x60000046c880>{number = 9, name = (null)}
execution - <NSThread: 0x604000078ac0>{number = 1, name = main}
execution - <NSThread: 0x600000469280>{number = 11, name = (null)}
execution - <NSThread: 0x60400026cb40>{number = 10, name = (null)}
execution - <NSThread: 0x60000046c880>{number = 9, name = (null)}
execution - <NSThread: 0x604000078ac0>{number = 1, name = main}
  • 自定義Operation

除了上面的兩種Operation以外蠕嫁,我們還可以自定義Operation锨天。自定義Operation需要繼承NSOperation類,并實現(xiàn)其main()方法剃毒,因為在調(diào)用start()方法的時候病袄,內(nèi)部會調(diào)用main()方法完成相關(guān)邏輯。所以如果以上的兩個類無法滿足你的欲望的時候赘阀,你就需要自定義了益缠。你想要實現(xiàn)什么功能都可以寫在里面。除此之外基公,你還需要實現(xiàn)cancel()在內(nèi)的各種方法幅慌。

創(chuàng)建隊列

看過上面的內(nèi)容就知道,我們可以調(diào)用一個NSOperation對象的start()方法來啟動這個任務(wù)轰豆,但是這樣做他們默認(rèn)是 同步執(zhí)行 的胰伍。就算是addExecutionBlock方法齿诞,也會在 當(dāng)前線程和其他線程 中執(zhí)行,也就是說還是會占用當(dāng)前線程骂租。這是就要用到隊列NSOperationQueue了掌挚。而且,按類型來說的話一共有兩種類型:主隊列菩咨、其他隊列吠式。只要添加到隊列,會自動調(diào)用任務(wù)的start()方法抽米。

  • 主隊列

細(xì)心的同學(xué)就會發(fā)現(xiàn)特占,每套多線程方案都會有一個主線程(當(dāng)然啦,說的是iOS中云茸,像pthread這種多系統(tǒng)的方案并沒有是目,因為UI線程理論需要每種操作系統(tǒng)自己定制)。這是一個特殊的線程标捺,必須串行懊纳。所以添加到主隊列的任務(wù)都會一個接一個地排著隊在主線程處理。

NSOperationQueue *queue = [NSOperationQueue mainQueue];
  • 其他隊列

因為主隊列比較特殊亡容,所以會單獨有一個類方法來獲得主隊列嗤疯。那么通過初始化產(chǎn)生的隊列就是其他隊列了,因為只有這兩種隊列闺兢,除了主隊列茂缚,其他隊列就不需要名字了。

注意:其他隊列的任務(wù)會在其他線程并行執(zhí)行屋谭。

//1.創(chuàng)建一個其他隊列    
NSOperationQueue *queue = [[NSOperationQueue alloc] init];

//2.創(chuàng)建NSBlockOperation對象
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"%@", [NSThread currentThread]);
}];

//3.添加多個Block
for (NSInteger i = 0; i < 5; i++) {
    [operation addExecutionBlock:^{
        NSLog(@"第%ld次:%@", i, [NSThread currentThread]);
    }];
}

//4.隊列添加任務(wù)
[queue addOperation:operation];

打印輸出

2015-07-28 20:26:28.463 test[18622:4443534] <NSThread: 0x7fd022c3ac10>{number = 5, name = (null)}
2015-07-28 20:26:28.463 test[18622:4443536] 第2次 - <NSThread: 0x7fd022e36d50>{number = 2, name = (null)}
2015-07-28 20:26:28.463 test[18622:4443535] 第0次 - <NSThread: 0x7fd022f237f0>{number = 4, name = (null)}
2015-07-28 20:26:28.463 test[18622:4443533] 第1次 - <NSThread: 0x7fd022d372b0>{number = 3, name = (null)}
2015-07-28 20:26:28.463 test[18622:4443534] 第3次 - <NSThread: 0x7fd022c3ac10>{number = 5, name = (null)}
2015-07-28 20:26:28.463 test[18622:4443536] 第4次 - <NSThread: 0x7fd022e36d50>{number = 2, name = (null)}

OK, 這時應(yīng)該發(fā)問了脚囊,大家將NSOperationQueueGCD的隊列 相比較就會發(fā)現(xiàn),這里沒有串行隊列桐磁,那如果我想要10個任務(wù)在其他線程串行的執(zhí)行怎么辦悔耘?

這就是蘋果封裝的妙處,你不用管串行我擂、并行衬以、同步、異步這些名詞扶踊。NSOperationQueue有一個參數(shù)maxConcurrentOperationCount最大并發(fā)數(shù)泄鹏,用來設(shè)置最多可以讓多少個任務(wù)同時執(zhí)行郎任。當(dāng)你把它設(shè)置為 1 的時候秧耗,他不就是串行了嘛!

NSOperationQueue還有一個添加任務(wù)的方法舶治,- (void)addOperationWithBlock:(void (^)(void))block;分井,這是不是和GCD差不多车猬?這樣就可以添加一個任務(wù)到隊列中了,十分方便尺锚。

NSOperation有一個非常實用的功能珠闰,那就是添加依賴。比如有 3 個任務(wù):A: 從服務(wù)器上下載一張圖片瘫辩,B:給這張圖片加個水印伏嗜,C:把圖片返回給服務(wù)器。這時就可以用到依賴了:

//1.任務(wù)一:下載圖片
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"下載圖片 - %@", [NSThread currentThread]);
    [NSThread sleepForTimeInterval:3.0];
}];

//2.任務(wù)二:打水印
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"打水印   - %@", [NSThread currentThread]);
    [NSThread sleepForTimeInterval:1.0];
}];

//3.任務(wù)三:上傳圖片
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"上傳圖片 - %@", [NSThread currentThread]);
    [NSThread sleepForTimeInterval:1.0];
}];

//4.設(shè)置依賴
[operation1 addDependency:operation3];      //任務(wù)二依賴任務(wù)一
[operation3 addDependency:operation2];      //任務(wù)三依賴任務(wù)二

//5.創(chuàng)建隊列并加入任務(wù)
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperations:@[operation3, operation2, operation1] waitUntilFinished:NO];

打印結(jié)果

打水印   - <NSThread: 0x600000276900>{number = 3, name = (null)}
上傳圖片 - <NSThread: 0x604000462400>{number = 4, name = (null)}
下載圖片 - <NSThread: 0x600000276900>{number = 3, name = (null)}
  • 注意:不能添加相互依賴伐厌,會死鎖承绸,比如 A依賴B,B依賴A挣轨。
  • 可以使用removeDependency來解除依賴關(guān)系军熏。
  • 可以在不同的隊列之間依賴,反正就是這個依賴是添加到任務(wù)身上的卷扮,和隊列沒關(guān)系荡澎。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市晤锹,隨后出現(xiàn)的幾起案子摩幔,更是在濱河造成了極大的恐慌,老刑警劉巖鞭铆,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件热鞍,死亡現(xiàn)場離奇詭異,居然都是意外死亡衔彻,警方通過查閱死者的電腦和手機薇宠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來艰额,“玉大人澄港,你說我怎么就攤上這事”冢” “怎么了回梧?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長祖搓。 經(jīng)常有香客問我狱意,道長,這世上最難降的妖魔是什么拯欧? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任详囤,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘藏姐。我一直安慰自己隆箩,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布羔杨。 她就那樣靜靜地躺著捌臊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪兜材。 梳的紋絲不亂的頭發(fā)上理澎,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天,我揣著相機與錄音曙寡,去河邊找鬼矾端。 笑死,一個胖子當(dāng)著我的面吹牛卵皂,可吹牛的內(nèi)容都是我干的秩铆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼灯变,長吁一口氣:“原來是場噩夢啊……” “哼殴玛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起添祸,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤滚粟,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后刃泌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體凡壤,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年耙替,在試婚紗的時候發(fā)現(xiàn)自己被綠了亚侠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡俗扇,死狀恐怖硝烂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情铜幽,我是刑警寧澤滞谢,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站除抛,受9級特大地震影響狮杨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜到忽,卻給世界環(huán)境...
    茶點故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一橄教、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦颤陶、人聲如沸颗管。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至帽馋,卻和暖如春搅方,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背绽族。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工姨涡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人吧慢。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓涛漂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親检诗。 傳聞我的和親對象是個殘疾皇子匈仗,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,654評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 一、前言 上一篇文章iOS多線程淺匯-原理篇中整理了一些有關(guān)多線程的基本概念逢慌。本篇博文介紹的是iOS中常用的幾個多...
    nuclear閱讀 2,050評論 6 18
  • 主隊列 細(xì)心的同學(xué)就會發(fā)現(xiàn)悠轩,每套多線程方案都會有一個主線程(當(dāng)然啦,說的是iOS中攻泼,像 pthread 這種多系統(tǒng)...
    京北磊哥閱讀 379評論 0 1
  • 在這篇文章中火架,我將為你整理一下 iOS 開發(fā)中幾種多線程方案,以及其使用方法和注意事項忙菠。當(dāng)然也會給出幾種多線程的案...
    張戰(zhàn)威ican閱讀 603評論 0 0
  • 學(xué)習(xí)多線程何鸡,轉(zhuǎn)載兩篇大神的帖子,留著以后回顧牛欢!第一篇:關(guān)于iOS多線程音比,你看我就夠了 第二篇:GCD使用經(jīng)驗與技巧...
    John_LS閱讀 619評論 0 3
  • 一、前言 本篇博文介紹的是iOS中常用的幾個多線程技術(shù): NSThread GCD NSOperation 由于a...
    和玨貓閱讀 577評論 0 1