NSThread/NSOperationQueue/GCD 多線程操作

什么是線程褥影?什么是主線程池户?什么是子線程?

在我們程序運(yùn)行期間,每個(gè)正在運(yùn)行的代碼段校焦,被稱為線程赊抖。

程序運(yùn)行期間,至少有一個(gè)線程寨典,該線程為主線程氛雪,主要負(fù)責(zé)刷新UI,比如添加控件耸成,刪除控件报亩,更新控件等。

如果遇到耗時(shí)的功能井氢,程序中有多個(gè)線程捆昏,除了主線程,其余的都是子線程毙沾。

子線程主要負(fù)責(zé)骗卜,耗時(shí)的任務(wù),比如左胞,網(wǎng)絡(luò)請(qǐng)求寇仓,處理大數(shù)據(jù)等。

iOS 如果遇到多個(gè)耗時(shí)的任務(wù)烤宙,或者要求遍烦,多個(gè)任務(wù)同時(shí)執(zhí)行。我們可以使用多線程編程技術(shù)躺枕,開(kāi)辟多個(gè)線程服猪,把任務(wù)放到其他進(jìn)程中執(zhí)行。

線程與線程之間獨(dú)立執(zhí)行拐云,互不干擾罢猪。

//iOS 中多線程方式

一,NSTread ? 線程類

? 1叉瘩,使用線程類膳帕,來(lái)開(kāi)辟線程

?二,NSobject分類方法

?使用場(chǎng)景:只想要一個(gè)操作薇缅,在開(kāi)辟的子線程中執(zhí)行危彩。

[self performSelectorInBackground:@selector(printString;) ?withObject:@"分類開(kāi)辟子線程方法"];

[self performSelectorInBackground:@selector(printString;)? withObject:@"分類開(kāi)辟子線程方法1"];

[self performSelectorInBackground:@selector(printString;)? withObject:@"分類開(kāi)辟子線程方法2"];

[self performSelectorInBackground:@selector(printString;)? withObject:@"分類開(kāi)辟子線程方法3"];

// 在主線程中執(zhí)行SEL方法,傳遞參數(shù)泳桦,方法執(zhí)行結(jié)束之前是否等待 ? ?yes 等待 ?汤徽,no不等待

// @"111"是作為參數(shù)傳遞進(jìn) 方法printString:?

[self performSelectorOnMainThread:@selector(printString:) withObject:@"111" waitUntilDone:YES];


主線程主要用來(lái)接受用戶相應(yīng)的操作,更新UI灸撰,因此谒府,我們添加UI漆羔,更新UI,以及刪除UI的操作狱掂,一定要放在主線程中執(zhí)行演痒。比如:label.text = @"aaa";



// 四 , GCD

GCD屬于函數(shù)級(jí)別的多線程趋惨,主要是分配不同功能的隊(duì)列鸟顺,提供給用戶使用。

因此器虾,我們?cè)谑褂肎CD時(shí)讯嫂,根據(jù)需求,選用不同功能的隊(duì)列解決問(wèn)題兆沙。

//1. gcd 串行隊(duì)列

- (IBAction)serialQueue:(id)sender

// ?何時(shí)使用: 當(dāng)多個(gè)任務(wù)具有依賴關(guān)系的時(shí)候欧芽。

// 比如:處理用戶輸入-》網(wǎng)絡(luò)請(qǐng)求-》處理請(qǐng)求結(jié)果 -》登錄

//1.創(chuàng)建一個(gè)串行隊(duì)列

dispatch_queue_t queue = dispatch_queue_create("queue",DISPATCH_QUEUE_SERIAL);

//2.添加任務(wù),任務(wù)只能是block或者是函數(shù)類型

// 兩個(gè)參數(shù)葛圃,前面一個(gè)是隊(duì)列名千扔,后面是添加的任務(wù),代碼塊block

dispatch_async(queue,^{

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

NSLog(@"I was borned");

});

dispatch_async(queue,^{

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

NSLog(@"i growed");

});

dispatch_async(queue,^{

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

NSLog(@"I married");

});

dispatch_async(queue,^{

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

NSLog(@"You were dead");

});

// 2.全局串行隊(duì)列是main函數(shù)執(zhí)行所在的主線程的隊(duì)列库正,我們稱為主隊(duì)列曲楚。主隊(duì)列是一個(gè)全局串行隊(duì)列,便于用戶訪問(wèn)

// 獲取主隊(duì)列

dispatch_queue_t mainQueue = dispatch_get_main_queue();

// 給主隊(duì)列添加刷新UI的操作

dispatch_async(mainQueue,^{

self.view.backgroundColor = [UIColor redColor];

});

// 并行隊(duì)列 ?conCurrentQueue

- (IBAction)conCurrentQueue:(id)sender

{

// 并行隊(duì)列是一種同時(shí)可以有多個(gè)任務(wù)并發(fā)執(zhí)行的隊(duì)列

// 使用方式:當(dāng)多個(gè)任務(wù)褥符,沒(méi)有依賴關(guān)系龙誊,誰(shuí)先執(zhí)行,誰(shuí)后執(zhí)行喷楣,都不重要趟大。

//1. 創(chuàng)建并行隊(duì)列

dispatch_queue_t currentQueue = dispatch_queue_create("queue",DISPATCH_QUEUE_CONCURRENT);

// 2.提交操作

dispatch_async(currentQueue,^{

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

NSLog(@"猴子一 連入游戲");

}

dispatch_async(currentQueue,^{

// block 塊內(nèi)封裝的可以是需要執(zhí)行的任務(wù)

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

NSLog(@"猴子二 連入游戲");

}

dispatch_async(currentQueue,^{

// block 塊內(nèi)封裝的可以是需要執(zhí)行的任務(wù)

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

NSLog(@"猴子三 連入游戲");

}

}

// 組提交方式

- (IBAction)group:(id)sender

{

// 什么是組提交方式

// 某些時(shí)候,我們需要把一些操作铣焊,歸為一類操作逊朽,比如,鏈接操作粗截,讀取操作惋耙。而鏈接操作和讀取操作中捣炬,又有多個(gè)操作熊昌。此時(shí)使用組提交方式。

//1湿酸、創(chuàng)建一個(gè)并行隊(duì)列

dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_CONCURRENT);

//2婿屹、創(chuàng)建一個(gè)組隊(duì)列

dispatch_group_t group1 = dispatch_group_create();

//3、提交

dispatch_group_async(group1, queue1, ^{

NSLog(@"玩家1連入游戲");

});

dispatch_group_async(group1, queue1, ^{

NSLog(@"玩家2連入游戲");

});

dispatch_group_async(group1, queue1, ^{

NSLog(@"玩家3連入游戲");

});

dispatch_group_async(group1, queue1, ^{

NSLog(@"玩家4連入游戲");

});

dispatch_group_async(group1, queue1, ^{

NSLog(@"玩家5連入游戲");

});

// 組中通知提交方式推溃,當(dāng)組中所有其他操作執(zhí)行完畢后昂利,它才會(huì)執(zhí)行

dispatch_group_notify(group1,queue1,^{

NSLog(@"所有玩家接入完畢,游戲開(kāi)始");

});

}

// barrier 障礙提交方式

- (IBAction)barrier:(id)sender

{

// barrier 提交方式,其實(shí)是把多個(gè)操作蜂奸,劃分為兩個(gè)部分犁苏,這兩個(gè)部分執(zhí)行方式都是并發(fā)執(zhí)行的。

// ?只要多一個(gè)barrier 就會(huì)劃分出來(lái)兩個(gè)部分

// ?通常用于前面有多個(gè)操作扩所,后面有多個(gè)操作围详,后面部分要等到前面部分執(zhí)行完畢再執(zhí)行

//1. 并行執(zhí)行

dispatch_queue_t queue = dispatch_queue_create("queue",DISPATCH_QUEUE_CONCURRENT);

//2.提交操作

dispatch_async(queue,^{

NSLog(@"網(wǎng)絡(luò)連接成功");

});

dispatch_async(queue,^{

NSLog(@"用戶請(qǐng)求成功“);

});

dispatch_async(queue,^{

NSLog(@"驗(yàn)證用戶名密碼");

});

// 障礙提交方式

dispatch_barrier_async(queue,^{

NSLog(@"驗(yàn)證完成");

});

dispatch_async(queue,^{

NSLog(@"讀取用戶數(shù)據(jù)");

});

}

// after 延遲執(zhí)行

- (IBAction)after:(id)after{

// 延遲執(zhí)行,多用于加載圖祖屏,線程睡眠等使用場(chǎng)景

// 1.從哪個(gè)時(shí)間點(diǎn)去

// 2. 過(guò)幾秒后

// 3.提交到哪個(gè)隊(duì)列中

// 4. 執(zhí)行block

dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(5*NSEC_PER_SEC)) , dispatch_get_main_queue(),^{

self.view.backgroundColor = [UIColor redColor];

// 延遲五秒助赞,把當(dāng)前控制器所在的視圖的背景顏色換為紅色

}); ??

}

// apply 重復(fù)提交執(zhí)行

- (IBAction)apply:(id)sender

{

// 使用場(chǎng)景:有多個(gè)任務(wù),需要提交到隊(duì)列中時(shí)袁勺,使用apply方式

//1. 把多個(gè)任務(wù)存儲(chǔ)到數(shù)組中

NSArray *array = @[@"圖片1",@"圖片2",@"圖片3",@"圖片4",@"圖片5"];

//2. 提交到一個(gè)并行隊(duì)列中

// 參數(shù)1. 數(shù)組個(gè)數(shù)雹食,重復(fù)執(zhí)行次數(shù)

// 參數(shù)2.提交到哪個(gè)隊(duì)列中

// 參數(shù)3.當(dāng)前執(zhí)行的次數(shù)

dispatch_apply(5,dispatch_get_global_queue(0,0),^(size_t i){

// i從0開(kāi)始到 5-1

NSLog(@"%@",array[i]);

});

}


// NSOperationQueue?

- (IBAction)operationQueue:(id)sender

{

// 使用場(chǎng)景,當(dāng)我們有多個(gè)任務(wù),都需要放倒子線程中執(zhí)行時(shí)期丰,使用操作隊(duì)列這種方式群叶,更為高效,隊(duì)列內(nèi)部給我們創(chuàng)建了合適的線程數(shù)钝荡。

// ?什么是操作隊(duì)列盖呼? 何時(shí)使用操作隊(duì)列?

// 操作隊(duì)列事以一個(gè)隊(duì)列化撕,內(nèi)部提交的是操作對(duì)象几晤,隊(duì)列中可以給我們開(kāi)辟適當(dāng)?shù)木€程數(shù)去解決多個(gè)要執(zhí)行的操作

// 操作隊(duì)列是以合適的線程數(shù),更加高效地解決需求

// 創(chuàng)建操作對(duì)象

NSInvocationOperation *invo1 = [[NSInvovationOperation alloc] initWithTarget:self selector:@selector(printString:) object:@"1111"];

NSInvocationOperation *invo2 = [[NSInvovationOperation alloc] initWithTarget:self selector:@selector(printString:) object:@"2222"];

NSInvocationOperation *invo3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(printString:) object:@"333"];

// 2.以block方式創(chuàng)建對(duì)象

NSBlockOperation *bo1 = [NSBlockOperation blockOperationWithBlock:^{

// block 內(nèi)部填寫我們要執(zhí)行的操作植阴,當(dāng)該操作對(duì)象執(zhí)行時(shí)蟹瘾,會(huì)調(diào)用block,執(zhí)行操作

NSLog(@"I");

}];

NSBlockOperation *bo2 = [NSBlockOperation blockOperationWithBlock:^{

// block 內(nèi)部填寫我們要執(zhí)行的操作掠手,當(dāng)該操作對(duì)象執(zhí)行時(shí)憾朴,會(huì)調(diào)用block,執(zhí)行操作

NSLog(@"lOVE");

}];

NSBlockOperation *bo3 = [NSBlockOperation blockOperationWithBlock:^{

//block 內(nèi)部填寫我們要執(zhí)行的操作喷鸽,當(dāng)該操作對(duì)象執(zhí)行時(shí)众雷,會(huì)調(diào)用block,執(zhí)行操作

NSLog(@"You");

}];


// 1. 創(chuàng)建一個(gè)操作隊(duì)列

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

// 設(shè)置操作隊(duì)列的最大并發(fā)數(shù)

queue1.maxConcurrentOperationCount = 3;

// 同一時(shí)間點(diǎn)做祝,能夠執(zhí)行的操作數(shù)

// 當(dāng)隊(duì)列的最大并發(fā)數(shù)為1時(shí)為砾省,串行隊(duì)列,大于1為并行隊(duì)列混槐。

// 如何讓并行隊(duì)列中编兄,某些任務(wù)按照順序執(zhí)行?

// ?給任務(wù)添加依賴關(guān)系

[invo2 addDependency:invo1];

[invo3 addDependency:invoke];

//把操作添加到操作隊(duì)列里面

//? ? [queue1 addOperation:invo1];

//? ? [queue1 addOperation:invo2];

//? ? [queue1 addOperation:invo3];

//把操作添加到操作隊(duì)列里面

[queue1 addOperation:bo1];

[queue1 addOperation:bo2];

[queue1 addOperation:bo3];

}


- (IBAction)block:(id)sender {

//? [self printNumber];

[NSThread detachNewThreadSelector:@selector(printNumber) ?toTarget:self withObject:nil];

}


- (IBAction)thread:(id)sender {

//1声登、開(kāi)辟一個(gè)線程

// [NSThread detachNewThreadSelector:@selector(printNumber) toTarget:self withObject:nil];

// 注意: detach 創(chuàng)建的線程狠鸳,自動(dòng)執(zhí)行揣苏,通常用于默認(rèn)執(zhí)行的操作。

// 2件舵、NSThread 開(kāi)辟的線程另一種方法? init

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

//初始化方法創(chuàng)建的線程卸察,需要我們手動(dòng)開(kāi)啟,使用start方法

[thread start];

//結(jié)束線程

// [thread cancel];

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

}

// 打印一個(gè)string

- (void)printString:(NSString *)string

{

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

}

- (IBAction)cankao:(id)sender {

NSLog(@"aaaaa");

}

//for 循環(huán)方法

- (void)printNumber

{

@autoreleasepool {

for (int i = 0; i < 655000000; i++) {

NSLog(@"%d",i);

}

}

}

- (IBAction)sync:(id)sender {

//同步提交方式會(huì)等 提交的操作執(zhí)行完畢后铅祸,再執(zhí)行后面的操作蛾派。

//同步提交方式會(huì)卡主線程。

dispatch_sync(dispatch_get_global_queue(0, 0), ^{

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

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

NSLog(@"%d",i);

}

});

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

NSLog(@"我在下面我在下面我在下面");

dispatch_sync(dispatch_get_global_queue(0, 0), ^{

NSLog(@"aaaaaaaaa");

});

}

void sum(void *string)

{

//注意傳遞過(guò)來(lái)的是什么類型就用什么類型打印个少。

NSLog(@"%s",string);

}

// 提交函數(shù)

- (IBAction)function:(id)sender {

dispatch_async_f(dispatch_get_main_queue(), "aaa", sum);

//獲取線程名

dispatch_queue_t queue = dispatch_queue_create("aaa", DISPATCH_QUEUE_CONCURRENT);

const char *name = dispatch_queue_get_label(queue);

NSLog(@"%@",[NSString stringWithUTF8String:(const char *)name]);

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末洪乍,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子夜焦,更是在濱河造成了極大的恐慌壳澳,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件茫经,死亡現(xiàn)場(chǎng)離奇詭異巷波,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)卸伞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門抹镊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人荤傲,你說(shuō)我怎么就攤上這事垮耳。” “怎么了遂黍?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵终佛,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我雾家,道長(zhǎng)铃彰,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任芯咧,我火速辦了婚禮牙捉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘敬飒。我一直安慰自己邪铲,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布驶拱。 她就那樣靜靜地躺著霜浴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蓝纲。 梳的紋絲不亂的頭發(fā)上阴孟,一...
    開(kāi)封第一講書(shū)人閱讀 51,573評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音税迷,去河邊找鬼永丝。 笑死,一個(gè)胖子當(dāng)著我的面吹牛箭养,可吹牛的內(nèi)容都是我干的慕嚷。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼毕泌,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼喝检!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起撼泛,我...
    開(kāi)封第一講書(shū)人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤挠说,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后愿题,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體损俭,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年潘酗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了杆兵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡仔夺,死狀恐怖琐脏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情缸兔,我是刑警寧澤骆膝,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站灶体,受9級(jí)特大地震影響阅签,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蝎抽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一政钟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧樟结,春花似錦养交、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至驮履,卻和暖如春鱼辙,著一層夾襖步出監(jiān)牢的瞬間廉嚼,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工倒戏, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留怠噪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓杜跷,卻偏偏與公主長(zhǎng)得像傍念,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子葛闷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

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