多線程的使用01

進(jìn)程和線程

進(jìn)程:正在運(yùn)行的程序
線程:基本執(zhí)行單元
一個(gè)進(jìn)程至少要一個(gè)線程
一個(gè)進(jìn)程的所有任務(wù)都是在線程中執(zhí)行
一個(gè)線程的任務(wù)是串行的,若一個(gè)線程有多個(gè)任務(wù)則需要按順序一個(gè)一個(gè)執(zhí)行,同一個(gè)時(shí)間內(nèi)豹休,一個(gè)線程只能執(zhí)行一個(gè)任務(wù)

多線程的概念

多線程的執(zhí)行原理:cpu的切換-時(shí)間片
每條線程可以并行執(zhí)行不同的任務(wù)的原理:同一時(shí)間內(nèi),單CPU(單核)只能處理一條線程谆甜,其實(shí)是CUP在多條線程之間調(diào)度擦酌。線程過多蛇更,CPU的負(fù)荷會(huì)過大闺鲸,會(huì)降低效

任務(wù)的同步執(zhí)行&異步執(zhí)行

任務(wù)同步執(zhí)行:一個(gè)接著一個(gè)筋讨,前一個(gè)沒有執(zhí)行完,后面不能執(zhí)行
任務(wù)異步執(zhí)行:任務(wù)同一時(shí)間可以執(zhí)行

多線程在ios開發(fā)中的應(yīng)用:

  • 主線程(UI線程):UI操作放到主線程摸恍,不要將耗時(shí)的操作放到主線程中
  • 子線程(后臺(tái)線程/非主線程):執(zhí)行耗時(shí)操作

多線程的創(chuàng)建

線程的生命周期:當(dāng)任務(wù)執(zhí)行完成之后被釋放掉

  • 線程的基本使用
//獲取主線程

NSThread *mainThread = [NSThread mainThread];

//獲取當(dāng)前線程

NSThread *currentThread = [NSThread currentThread];

//判斷當(dāng)前線程是否是主線程-類/對(duì)象方法

BOOL ismain1= [NSThread isMainThread];

BOOL ismain2 = [currentThread isMainThread];

1悉罕、pthread的基本使用方法:

//創(chuàng)建pthread線程對(duì)象

pthread_t pthreadB;

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

//參數(shù)一:線程對(duì)象,參數(shù)二:線程的屬性立镶,參數(shù)三:指向函數(shù)的指針蛮粮,參數(shù)四:函數(shù)的參數(shù)

pthread_create(&pthreadB, NULL, task, @"123");

//線程函數(shù)的格式

void *task (void * pagem)
{
  NSLog(@"%@-%@",[NSThread currentThread],pagem);
  return NULL;
}

2、NSThread方法:OC谜慌,用戶管理周期,創(chuàng)建方法-三種:

//方法一莺奔,object:代表的是函數(shù)的參數(shù)欣范,只有方法一可以返回線程,給線程設(shè)置屬性
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(run:) object:@"abc"];
[thread start];

//方法二令哟,分離 
[NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"123"];

//方法三恼琼,后臺(tái)
[self performSelectorInBackground:@selector(run:) withObject:@"ABC"];
//線程調(diào)用方法

//方法一:指定線程去執(zhí)行任務(wù)
[self performSelector:@selector(text2) onThread:self.thread withObject:nil waitUntilDone:YES]; 

//方法二:放到主線程中
[self performSelectorOnMainThread:@selector(text2) withObject:nil waitUntilDone:YES]; 

//方法三:在子線程中執(zhí)行任務(wù)
[self performSelectorInBackground:@selector(text2) withObject:nil];
//線程的屬性
//線程的名字 
thread.name = @"A"; 
//線程的優(yōu)先級(jí),范圍在0-1之間屏富,默認(rèn)為0.5 
thread1.threadPriority = 1;

//線程的阻塞-兩種方法
//參數(shù)是事件
 [NSThread sleepForTimeInterval:2.0]; 

//參數(shù)是NSDate
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:3.0]];

//線程的強(qiáng)制退出
[NSThread exit];

3晴竞、GCD:C語言編寫的,不需要自己管理生命周期

4狠半、NSOperation:OC噩死,不需要自己管理生命周期

線程的安全性問題:

主線程也是不安全的颤难,所以將所有的UI操作都放到主線程中,使UI操作變得安全
互斥鎖-將需要加鎖的代碼(多條線程搶奪同一個(gè)資源)寫入互斥鎖中已维,token代表唯一的鎖行嗤,一般設(shè)置為self 。
注意: 注意加鎖的位置垛耳。
注意加鎖的條件:多線程共享同一個(gè)資源 栅屏。
注意加鎖會(huì)消耗性能。注意加鎖的結(jié)果會(huì)造成線程的同步(多條線程在同一個(gè)線上執(zhí)行堂鲜,按照順序)栈雳。

@synchronized (<#token#>)
{

}

屬性nonatomic和atomic的區(qū)別:
atomic:原子性,安全(同一時(shí)間只有一個(gè)線程進(jìn)行賦值操作)缔莲,會(huì)給屬性的set方法加鎖哥纫,但是會(huì)消耗資源(其他線程要判斷)-自旋鎖。
nonatomic:非原子性酌予,不安全(同一時(shí)間可以有多個(gè)線程進(jìn)行讀和寫)磺箕,一般建議。

自旋鎖&同步鎖

自旋鎖:如果發(fā)現(xiàn)有其它線程正在鎖定代碼,線程會(huì)用死循環(huán)的方式,一直等待鎖定的代碼執(zhí)行完成,自旋鎖更適合執(zhí)行不耗時(shí)的代碼 抛虫。(只是對(duì)set方法進(jìn)行鎖松靡,不斷的判斷set方法鎖是否打開(當(dāng)set方法是耗時(shí)操作時(shí),會(huì)卡死)atomic)
同步鎖:如果發(fā)現(xiàn)其他線程正在執(zhí)行鎖定代碼,線程會(huì)進(jìn)入休眠(就緒狀態(tài)),等其它線程時(shí)間片到打開鎖后,線程會(huì)被喚醒(執(zhí)行) 建椰。(鎖的范圍沒有定(set和get方法都鎖)雕欺,而且線程是等待,不是一直判斷set方法鎖是否打開)

@synchronized (<#token#>) { }

線程間的通信

方法兩種:
performSelectorOnMainThread:調(diào)轉(zhuǎn)到主線程
performSelector:onThread:調(diào)轉(zhuǎn)到線程(包括主線程)

//參數(shù)一:回到主線程要調(diào)用的哪個(gè)方法
//參數(shù)二:前面方法要傳遞的參數(shù)
//參數(shù)三:是否等待棉姐,YES屠列,先調(diào)轉(zhuǎn)線程的方法,后執(zhí)行原方法
//NO伞矩,先執(zhí)行原方法的然后再執(zhí)行線程的方法
[self performSelectorOnMainThread:@selector(getImage:) withObject:img waitUntilDone:YES];
//簡(jiǎn)寫笛洛,不需要?jiǎng)?chuàng)建getImage:方法,self.imageView中自帶setImage:方法,線程的切換
[self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:img waitUntilDone:NO];

[self performSelector:@selector(getImage:) onThread:[NSThread mainThread] withObject:img waitUntilDone:YES];

下載圖片:
1乃坤、配置info.plist文件:APP TransportSecurity Settings ->Allow Arbitrary Loads : YES
2苛让、代碼:

NSURL *url = [NSURL URLWithString:@"http://"];
NSData *data = [NSData dataWithContentsOfURL:url];
self.imageView.image = [UIImage imageWithData:data];

獲取時(shí)間差(總結(jié))

//方法一
NSDate *start = [NSDate date];//當(dāng)前的時(shí)間
NSDate *end = [NSDate date];//當(dāng)前的時(shí)間
double interval = [end timeIntervalSinceDate:start];

//方法二:
CFTimeInterval start1 = CFAbsoluteTimeGetCurrent();
CFTimeInterval end1 = CFAbsoluteTimeGetCurrent();
double intervar1 = end1-start1;

GCD

GCD的基本使用-關(guān)鍵dispacth

缺點(diǎn):不能控制開子線程的個(gè)數(shù)

任務(wù)和隊(duì)列

  • 任務(wù):需要的操作

  • 隊(duì)列:存放任務(wù):先進(jìn)先出

函數(shù)

  • 同步函數(shù):只能在當(dāng)前線程中執(zhí)行任務(wù),不具備開啟新線程的能力-dispatch_sync湿诊,立刻執(zhí)行狱杰,如果我沒有執(zhí)行完畢,那么后面的也不能執(zhí)行

  • 異步函數(shù):可以在新線程中執(zhí)行任務(wù)厅须,具備開啟新線程的能力-dispatch_async仿畸,如果我沒有執(zhí)行完畢,那么后面的也可以執(zhí)行 隊(duì)列

隊(duì)列

  • 并發(fā)/行隊(duì)列:

1、以先進(jìn)先出的方式错沽,并發(fā)調(diào)度隊(duì)列中的任務(wù)執(zhí)行

2簿晓、如果當(dāng)前調(diào)度的任務(wù)是同步執(zhí)行的,會(huì)等待任務(wù)執(zhí)行完成后甥捺,再調(diào)度后續(xù)的任務(wù)

3抢蚀、如果當(dāng)前調(diào)度的任務(wù)是異步執(zhí)行的,同時(shí)底層線程池有可用的線程資源镰禾,會(huì)再新的線程調(diào)度后續(xù)任務(wù)的執(zhí)行

  • 串行隊(duì)列:

1皿曲、以先進(jìn)先出的方式,順序調(diào)度隊(duì)列中的任務(wù)執(zhí)行

2吴侦、無論隊(duì)列中所指定的執(zhí)行任務(wù)函數(shù)是同步還是異步屋休,都會(huì)等待前一個(gè)任務(wù)執(zhí)行完成后,再調(diào)度后面的任務(wù)

主隊(duì)列 特殊的串行隊(duì)列备韧,代表主線程 不開線程劫樟,同步執(zhí)行 主隊(duì)列特點(diǎn):如果主線程正在執(zhí)行代碼暫時(shí)不調(diào)度任務(wù),等主線程執(zhí)行結(jié)束后在執(zhí)行任務(wù) 主隊(duì)列又叫 全局串行隊(duì)列

任務(wù)和隊(duì)列

同步和異步:能不能開啟新線程,同步不開织堂,異步可以開

并發(fā)和串行:任務(wù)的執(zhí)行方式叠艳,并發(fā)大家一起跑,串行一個(gè)任務(wù)接著一個(gè)任務(wù)執(zhí)行

//創(chuàng)建并發(fā)隊(duì)列易阳,參數(shù)一:C語言的字符串附较,標(biāo)簽DISPATCH_QUEUE_SERIAL代表串行隊(duì)列DISPATCH_QUEUE_CONCURRENT代表并行隊(duì)列

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

//創(chuàng)建異步任務(wù),添加到隊(duì)列中潦俺,簡(jiǎn)介的寫法

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

//獲取全局并發(fā)隊(duì)列拒课,參數(shù)一:優(yōu)先級(jí),DISPATCH_QUEUE_PRIORITY_BACKGROUND 最低,DISPATCH_QUEUE_PRIORITY_DEFAULT 默認(rèn)

//dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

//dispatch_get_global_queue(0,0);

隊(duì)列和任務(wù)的執(zhí)行方式

  • 異步函數(shù)+并發(fā)隊(duì)列: 可以創(chuàng)建線程事示,執(zhí)行順序不固定早像,線程可以復(fù)用(優(yōu)化)

  • 異步函數(shù)+同步隊(duì)列: 可以創(chuàng)建線程,只開一個(gè)線程肖爵,在當(dāng)前線程中串行執(zhí)行任務(wù)卢鹦,執(zhí)行順序固定

  • 同步函數(shù)+并發(fā)隊(duì)列: 不可以創(chuàng)建線程,任務(wù)串行

  • 同步函數(shù)+串行隊(duì)列: 不可以創(chuàng)建線程劝堪,任務(wù)串行

主隊(duì)列

//獲取主隊(duì)列,全局同步隊(duì)列
dispatch_queue_t queue = dispatch_get_main_queue();

主隊(duì)列和任務(wù)的執(zhí)行方式

主隊(duì)列是GCD自帶的一種特殊的串行隊(duì)列
放到主隊(duì)列的任務(wù)法挨,都會(huì)放到主線程中執(zhí)行
主線程的任務(wù)執(zhí)行完之后,主隊(duì)列才會(huì)調(diào)度主線程去執(zhí)行block的任務(wù)

  • 異步函數(shù)+主隊(duì)列:不會(huì)開子線程幅聘,在主線程中串行執(zhí)行

  • 同步函數(shù)+主隊(duì)列:產(chǎn)生了死鎖(當(dāng)執(zhí)行的當(dāng)前函數(shù)是主線程時(shí))

  • 原因:主隊(duì)列和主線程相互等待會(huì)造成死鎖。 在主線程空閑時(shí)才會(huì)調(diào)度主隊(duì)列中的任務(wù)在主線程執(zhí)行

GCD之間的通信切換

//嵌套函數(shù)
dispatch_sync(queue, ^{
  NSURL *url = [NSURL URLWithString:@"http://"];
  NSData *data = [NSData dataWithContentsOfURL:url];

//調(diào)轉(zhuǎn)到主線程中
dispatch_async(dispatch_get_main_queue(), ^{
  self.imageView.image = [UIImage imageWithData:data];
  });
});

GCD的常用函數(shù)

延時(shí):

方法一:

[self performSelector:@selector(say) withObject:self afterDelay:2];

方法二:

[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(say) userInfo:nil repeats:nil];

方法三:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), queue, ^{

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

});

一次性代碼

  • 在程序的生命周期中只執(zhí)行一次窃植,不能放到懶加載中
dispatch_once_t once ;

dispatch_once(&once, ^{

NSLog(@"------");

});

自動(dòng)釋放池的使用

1帝蒿、當(dāng)創(chuàng)建了許多臨時(shí)變量的時(shí)候,需要加自動(dòng)釋放池
2巷怜、開啟子線程的時(shí)候也需要加自動(dòng)釋放池

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末葛超,一起剝皮案震驚了整個(gè)濱河市暴氏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌绣张,老刑警劉巖答渔,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異侥涵,居然都是意外死亡沼撕,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門芜飘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來务豺,“玉大人,你說我怎么就攤上這事嗦明×ぃ” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵娶牌,是天一觀的道長奔浅。 經(jīng)常有香客問我,道長诗良,這世上最難降的妖魔是什么汹桦? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮累榜,結(jié)果婚禮上营勤,老公的妹妹穿的比我還像新娘。我一直安慰自己壹罚,他們只是感情好葛作,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著猖凛,像睡著了一般赂蠢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辨泳,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天虱岂,我揣著相機(jī)與錄音,去河邊找鬼菠红。 笑死第岖,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的试溯。 我是一名探鬼主播蔑滓,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了键袱?” 一聲冷哼從身側(cè)響起燎窘,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蹄咖,沒想到半個(gè)月后褐健,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡澜汤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年蚜迅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片银亲。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡慢叨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出务蝠,到底是詐尸還是另有隱情拍谐,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布馏段,位于F島的核電站轩拨,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏院喜。R本人自食惡果不足惜亡蓉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望喷舀。 院中可真熱鬧砍濒,春花似錦、人聲如沸硫麻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拿愧。三九已至杠河,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間浇辜,已是汗流浹背券敌。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留柳洋,地道東北人待诅。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像熊镣,于是被迫代替她去往敵國和親咱士。 傳聞我的和親對(duì)象是個(gè)殘疾皇子立由,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

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