多線程

pthread

一套用C語言的通用的多線程API孝情,可以跨平臺、可移植洒嗤,適用于windows箫荡、Linux、Unix平臺渔隶,由于使用難度較大羔挡,線程生命周期由程序員管理線程,幾乎不怎么使用

//    使用pthread創(chuàng)建線程對象

pthread_t thread;

NSString *name = @"ceshi";

//    使用pthread創(chuàng)建線程

//    第一個參數(shù):線程對象地址

//    第二個參數(shù):線程屬性

//    第三個參數(shù):指向函數(shù)的執(zhí)行

//    第四個參數(shù):傳遞給該函數(shù)的參數(shù)

pthread_create(&thread, NULL, run, (__bridge void *)(name));

NSThread

使用OC更傾向于面向?qū)ο蠹浒Γ啽闶褂媒首啤>€程生命周期由程序員管理線程,偶爾使用呈野。

//    第一個參數(shù):目標(biāo)對象

 //    第二個參數(shù):選擇器低矮,線程啟動要調(diào)用哪個方法

 //    第三個參數(shù):前面方法要接收的參數(shù)(最多只能接收一個參數(shù),沒有則傳nil)
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
//    啟動線程
[thread start];

+ (NSThread *)mainThread;  獲得主線程

- (BOOL)isMainThread;  是否為主線程

+ (BOOL)isMainThread;  是否為主線程

//    獲得當(dāng)前線程
NSThread *current = [NSThread currentThread];

//    啟動線程

- (void)start;

 //    進(jìn)入就緒狀態(tài) ->運(yùn)行狀態(tài)被冒。當(dāng)線程任務(wù)執(zhí)行完畢军掂,自動進(jìn)入死亡狀態(tài)

//    設(shè)置線程的優(yōu)先級,注意線程優(yōu)先級的取值范圍為0.0~1.0之間,1.0表示線程的優(yōu)先級最高,如果不設(shè)置該值昨悼,那么理想狀態(tài)下默認(rèn)為0.5

thread.threadPriority = 1.0;

[NSThread exit]; //    退出當(dāng)前線程

[NSThread sleepForTimeInterval:2.0]; //    阻塞線程

[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]]; //    阻塞線程

/********************************************另外兩種創(chuàng)建線程方法*******************************************/
//    第二種創(chuàng)建線程的方式:分離出一條子線程

//    特點(diǎn):自動啟動線程蝗锥,無法對線程進(jìn)行更詳細(xì)的設(shè)置

//     第一個參數(shù):線程啟動調(diào)用的方法

//     第二個參數(shù):目標(biāo)對象

 //    第三個參數(shù):傳遞給調(diào)用方法的參數(shù)
[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];

//    第三種創(chuàng)建線程的方式:后臺線程

//    特點(diǎn):自動啟動縣城,無法進(jìn)行更詳細(xì)設(shè)置
[self performSelectorInBackground:@selector(run) withObject:nil];

/********************************************線程間通訊*******************************************/

//    線程間通信常用方法
//    開啟一條子線程來do something
[NSThread detachNewThreadSelector:@selector(doSomething) toTarget:self withObject:nil];

-(void) doSomething{
//    回到主線程刷新UI
//    第一種方式

    [self performSelectorOnMainThread:@selector(showSomething:) withObject:image waitUntilDone:YES];

//    第二種方式

    [self.imageView performSelectorOnMainThread:@selector(showSomething:) withObject:image waitUntilDone:YES];

//    第三種方式

    [self.imageView performSelector:@selector(showSomething:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES];
}

GCD (Grand Central Dispatch)

C語言幔戏,GCD是蘋果公司為多核的并行運(yùn)算提出的解決方案,會自動利用更多的CPU內(nèi)核(比如雙核玛追、四核),會自動管理線程的生命周期(創(chuàng)建線程税课、調(diào)度任務(wù)闲延、銷毀線程),程序員只需要告訴GCD想要執(zhí)行什么任務(wù),不需要編寫任何線程管理代碼.

//  GCD中有2個用來執(zhí)行任務(wù)的函數(shù)

//  用同步的方式執(zhí)行任務(wù)
//  queue:隊(duì)列   block:任務(wù)
dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);

//  用異步的方式執(zhí)行任務(wù)(主要掌握)
dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

GCD的隊(duì)列可以分為2大類型 :

  • 并發(fā)隊(duì)列(Concurrent Dispatch Queue)(并發(fā)功能只有在異步(dispatch_async)函數(shù)下才有效)
  • 串行隊(duì)列(Serial Dispatch Queue)

并發(fā)隊(duì)列

//    使用dispatch_get_global_queue函數(shù)獲得全局的并發(fā)隊(duì)列

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

//    (里面的參數(shù)第一個為優(yōu)先級,可以默認(rèn)為固定寫法)列

//    全局并發(fā)隊(duì)列的優(yōu)先級

#define DISPATCH_QUEUE_PRIORITY_HIGH 2  高

#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0  默認(rèn)(中)

#define DISPATCH_QUEUE_PRIORITY_LOW (-2)  低

#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN  后臺

串行隊(duì)列

//    GCD中獲得串行有2種途徑

//    1.使用dispatch_queue_create函數(shù)創(chuàng)建串行隊(duì)列

//    dispatch_queue_t

//    dispatch_queue_create(const char*label,  隊(duì)列名稱

//    dispatch_queue_attr_t attr);  隊(duì)列屬性韩玩,一般用NULL即可

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

dispatch_queue_t queue = dispatch_queue_create("cn.queue", NULL);

dispatch_release(queue); //   非ARC需要釋放手動創(chuàng)建的隊(duì)列

//    2.使用主隊(duì)列(跟主線程相關(guān)聯(lián)的隊(duì)列,肯定是串行隊(duì)列)

//    主隊(duì)列是GCD自帶的一種特殊的串行隊(duì)列

//    放在主隊(duì)列中的任務(wù)垒玲,都會放到主線程中執(zhí)行

//    使用dispatch_get_main_queue()獲得主隊(duì)列

dispatch_queue_t queue = dispatch_get_main_queue();

延時執(zhí)行

[self performSelector:@selector(run) withObject:nil afterDelay:2.0];
//    使用GCD函數(shù)
//    DISPATCH_TIME_NOW:現(xiàn)在開始的意思
//    2.0 * NSEC_PER_SEC:設(shè)置的秒數(shù)(直接更改數(shù)字即可)
//    dispatch_get_main_queue():主隊(duì)列的意思

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

   //     2秒后執(zhí)行這里的代碼... 在哪個線程執(zhí)行,跟隊(duì)列類型有關(guān)
});

一次性代碼

//    使用dispatch_once函數(shù)能保證某段代碼在程序運(yùn)行過程中只被執(zhí)行1次

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{


    //     程序運(yùn)行過程中,永遠(yuǎn)只執(zhí)行1次的代碼(這里面默認(rèn)是線程安全的)

});

隊(duì)列組

//    有這么1種需求首先:分別異步執(zhí)行2個耗時的操作 ; 其次:等2個異步操作都執(zhí)行完畢后找颓,再回到主線程執(zhí)行操作
dispatch_group_t group =  dispatch_group_create();

dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

     //    執(zhí)行1個耗時的異步操作

});

dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    //     執(zhí)行1個耗時的異步操作

});

dispatch_group_notify(group, dispatch_get_main_queue(), ^{

     //    等前面的異步操作都執(zhí)行完畢后合愈,回到主線程...

});

//    它會等組里面所有的任務(wù)(同上的兩個block代碼內(nèi)容)都執(zhí)行完了以后,它會調(diào)用_notify里面的這個block;

GCD基本使用
01 異步函數(shù) + 并發(fā)隊(duì)列:開啟多條線程,并發(fā)執(zhí)行任務(wù)

02 異步函數(shù) + 串行隊(duì)列:開啟一條線程,串行執(zhí)行任務(wù)

03 同步函數(shù) + 并發(fā)隊(duì)列:不開線程佛析,串行執(zhí)行任務(wù)

04 同步函數(shù) + 串行隊(duì)列:不開線程益老,串行執(zhí)行任務(wù)

05 異步函數(shù) + 主隊(duì)列:不開線程,在主線程中串行執(zhí)行任務(wù)

06 同步函數(shù) + 主隊(duì)列:不開線程寸莫,串行執(zhí)行任務(wù)(注意死鎖發(fā)生)

07 注意同步函數(shù)和異步函數(shù)在執(zhí)行順序上面的差異

NSOperation

OC語言捺萌,基于GCD,切比GCD多了一些更便捷的實(shí)用功能膘茎,更加面向?qū)ο蠡?桃纯,線程生命周期自動線程管理且經(jīng)常使用。

配合使用NSOperation和NSOperationQueue也能實(shí)現(xiàn)多線程編程披坏。

首先將需要執(zhí)行的操作封裝到一個NSOperation對象中态坦,然后將NSOperation對象添加到NSOperationQueue中,系統(tǒng)會自動將NSOperationQueue中的NSOperation取出來棒拂,將取出的NSOperation封裝的操作放到一條新線程中執(zhí)行伞梯。

NSOperation的子類:

NSInvocationOperation
NSBlockOperation
自定義子類繼承NSOperation,實(shí)現(xiàn)內(nèi)部相應(yīng)的方法

NSInvocationOperation

//    創(chuàng)建NSInvocationOperation對象

- (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;

//    調(diào)用start方法開始執(zhí)行操作

- (void)start;

//    一旦執(zhí)行操作帚屉,就會調(diào)用target的sel方法
//    默認(rèn)情況下壮锻,調(diào)用了start方法后并不會開一條新線程去執(zhí)行操作,而是在當(dāng)前線程同步執(zhí)行操作,只有將NSOperation放到一個NSOperationQueue中涮阔,才會異步執(zhí)行操作

NSBlockOperation

//    創(chuàng)建NSBlockOperation對象

+ (id)blockOperationWithBlock:(void (^)(void))block;

//    通過addExecutionBlock:方法添加更多的操作

- (void)addExecutionBlock:(void (^)(void))block;

//    注意:只要NSBlockOperation封裝的操作數(shù) > 1猜绣,就會異步執(zhí)行操作

NSOperationQueue
NSOperation可以調(diào)用start方法來執(zhí)行任務(wù),但默認(rèn)是同步執(zhí)行的

//    添加操作到NSOperationQueue中

- (void)addOperation:(NSOperation *)op;

- (void)addOperationWithBlock:(void (^)(void))block;

最大并發(fā)數(shù)

-(NSInteger)maxConcurrentOperationCount;

- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;

隊(duì)列的取消敬特、暫停掰邢、恢復(fù)

//    取消隊(duì)列的所有操作

- (void)cancelAllOperations;

//    提示:也可以調(diào)用NSOperation的- (void)cancel方法取消單個操作(在內(nèi)存中給刪除了)


//    暫停和恢復(fù)隊(duì)列

- (void)setSuspended:(BOOL)b;  //    YES代表暫停隊(duì)列,再設(shè)置為NO代表恢復(fù)之前的隊(duì)列

- (BOOL)isSuspended;

操作優(yōu)先級

- (NSOperationQueuePriority)queuePriority;

- (void)setQueuePriority:(NSOperationQueuePriority)p;

//    優(yōu)先級的取值

NSOperationQueuePriorityVeryLow = -8L,

NSOperationQueuePriorityLow = -4L,

NSOperationQueuePriorityNormal = 0,

NSOperationQueuePriorityHigh = 4,

NSOperationQueuePriorityVeryHigh = 8

互斥鎖使用格式

@synchronized(鎖對象) {  需要鎖定的代碼  }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末伟阔,一起剝皮案震驚了整個濱河市辣之,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌皱炉,老刑警劉巖怀估,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異合搅,居然都是意外死亡多搀,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門灾部,熙熙樓的掌柜王于貴愁眉苦臉地迎上來康铭,“玉大人,你說我怎么就攤上這事赌髓〈犹伲” “怎么了催跪?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長夷野。 經(jīng)常有香客問我懊蒸,道長,這世上最難降的妖魔是什么悯搔? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任榛鼎,我火速辦了婚禮,結(jié)果婚禮上鳖孤,老公的妹妹穿的比我還像新娘者娱。我一直安慰自己,他們只是感情好苏揣,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布黄鳍。 她就那樣靜靜地躺著,像睡著了一般平匈。 火紅的嫁衣襯著肌膚如雪框沟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天增炭,我揣著相機(jī)與錄音忍燥,去河邊找鬼。 笑死隙姿,一個胖子當(dāng)著我的面吹牛梅垄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播输玷,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼队丝,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了欲鹏?” 一聲冷哼從身側(cè)響起机久,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赔嚎,沒想到半個月后膘盖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡尤误,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年侠畔,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片袄膏。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡践图,死狀恐怖掺冠,靈堂內(nèi)的尸體忽然破棺而出沉馆,到底是詐尸還是另有隱情码党,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布斥黑,位于F島的核電站揖盘,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏锌奴。R本人自食惡果不足惜兽狭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鹿蜀。 院中可真熱鬧箕慧,春花似錦、人聲如沸茴恰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽往枣。三九已至伐庭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間分冈,已是汗流浹背圾另。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留雕沉,地道東北人集乔。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像坡椒,于是被迫代替她去往敵國和親饺著。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355

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