網絡多線程的入門級理解

模擬耗時操作

  • 耗時操作對UI的影響 : 會卡死UI / 界面 / 主線程
  • 如何解決耗時操作卡死主線程?
    • 使用多線程技術,把耗時的操作放進子線程中執(zhí)行,使得主線程有資源處理UI
  • 多線程的核心思想 : 把耗時操作放到子線程異步執(zhí)行

多線程基本概念

同步和異步

  • 同步和異步是任務 / 代碼 執(zhí)行的兩種方式

同步

  • 多個任務按順序依次執(zhí)行,就是同步執(zhí)行

異步

  • 多個任務同時執(zhí)行,就是異步執(zhí)行
  • 如何保證多個任務同時執(zhí)行?
    • 開線程,開多個線程,就可以保證多個任務同時執(zhí)行
  • 提示 : 凡是遇到異步 / 多線程 / 耗時操作 第一反應就是需要開啟新的子線程
  • 學習多線程就是為了如何讓任務在子線程異步執(zhí)行

進程和線程

進程

  • 系統(tǒng)中正在運行的應用程序叫做進程
  • 進程可以類必成公司

線程 / 多線程

  • 程序一啟動就會默認開啟一個線程,稱之為主線程
  • 線程是進程最基本的執(zhí)行單元,進程里面所有的任務都在線程中執(zhí)行的
  • 一個進程,可以開啟多個線程,稱之為多線程

多線程執(zhí)行原理

  • CPU在多個線程之間,快速來回的切換,調度線程執(zhí)行任務,如果切換的速度足夠快,就造成多個任務同時執(zhí)行的假象

多線程優(yōu)缺點

優(yōu)點

  • 可以適當提高程序執(zhí)行的效率 (開啟多個線程下載視頻)

缺點

  • 前提 : 當線程非常多的時候,就暴露缺點
  • 會消耗大量的CPU資源
  • 時間開銷 / 空間開銷
  • 多線程的使用原則 : 能不用就不用,如果非要用,就簡單的使用,少用

主線程

  • 作用 : 刷新UI / 處理UI事件
  • 使用時的注意點 : 不要把耗時操作放到主線程中執(zhí)行

pthread

  • 學習pthread的目的 : 就是為了復習C語言相關的知識點
  • 在C語言中,一般帶_t / _ref標識數(shù)據(jù)類型
  • NULL : 表示空地址,一般在C語言使用;
  • nil : 表示空對象,一般在OC使用;
  • 其實,NULLh和nil本質上沒有半點兒區(qū)別
  • void *(*)(void *) : 表示指向函數(shù)的指針,即函數(shù)名;函數(shù)名就是表示函數(shù)地址;
  • 數(shù)組地址就是數(shù)組名或者數(shù)組第0個角標元素的地址
  • void * 表示可以指向任何地址的指針,代表任意數(shù)據(jù)類型;類似于OC的id;
返回值    函數(shù)名    函數(shù)參數(shù)
void *    (*)    (void *)

橋接

  • 使用場景 : 在C語言和OC語言混合開發(fā)時,需要做數(shù)據(jù)類型轉換,有時候需要使用橋接;
  • 橋接作用 : 在做數(shù)據(jù)類型轉換時,告訴編譯器如何管理C語言的內存
  • 提示 : 在ARC環(huán)境下,編譯器在編譯時,不會自動管理C語言申請的內存空間
  • 提示: 在ARC環(huán)境下,加上__bridge 表示告訴編譯器C語言申請的內存也是自動管理的,因為大環(huán)境是ARC的
  • 提問 : MRC環(huán)境下,需要使用__bridge 嗎? 不需要,因為本來就是手動管理的

NSThread創(chuàng)建線程三種方式

構造方法

  • 可以拿到線程對象
  • 需要自己啟動線程
// 創(chuàng)建線程對象
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(demo:) object:@"alloc"];
// 啟動線程
[thread start];

類方法

  • 不可以拿到線程對象
  • 不需要自己啟動線程
[NSThread detachNewThreadSelector:@selector(demo:) toTarget:self withObject:@"detach"];

NSObject分類方法

  • 不可以拿到線程對象
  • 不需要自己啟動線程
[self performSelectorInBackground:@selector(demo:) withObject:@"perform"];

target和selector的關系

  • 執(zhí)行哪個對象的哪個方法
  • 需求 : 執(zhí)行Person對象的run方法,run方法需要在子線程執(zhí)行
// 創(chuàng)建線程對象
NSThread *thread = [[NSThread alloc] initWithTarget:_p selector:@selector(run:) object:@"person"];
// 啟動線程
[thread start];

線程生命周期 / 線程狀態(tài)

  • 新建狀態(tài)
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(demo) object:nil];
  • 就緒狀態(tài)
[thread start];
  • 運行狀態(tài) : 程序員無法干預
  • 阻塞狀態(tài) : 調用sleep方法 / 添加互斥鎖(同步鎖)
  • 死亡狀態(tài)
    • 正常死亡 : 任務執(zhí)行結束
    • 異常死亡 : exit

線程屬性

  • name : 標識唯一的線程對象,方便定位線程對象
  • threadPriority : 決定了線程有更多的機會被CPU調度執(zhí)行;等同于qualityOfService;實際開發(fā)中千萬不要隨意修改
  • stackSize : 線程對象占用內存空間大小.主線程 / 子線程 512KB

多線程訪問共享資源 (會造成線程安全問題)

  • 當多個線程同時操作共享資源,就會出現(xiàn)線程安全問題
  • 解決辦法 : 加鎖 (互斥鎖 / 同步鎖)
  • 互斥鎖 / 同步鎖 : 使用了線程同步技術
  • 特點 : 可以保證被鎖定的代碼,同一時間只有一個線程可以訪問
  • self : 表示互斥鎖的參數(shù);互斥鎖的參數(shù),又叫做鎖對象;
  • 鎖對象 : 任何繼承自NSObject的對象,都可以作為互斥鎖的參數(shù);內部有把鎖,默認是開啟的
  • 鎖對象必須是全局的對象;self是最方便獲取的全局的鎖對象
  • 局部鎖對象是鎖不住的,因為每次線程進來之前會新建一把鎖
  • 提示 : 加鎖的事情,不是再客戶端操作的;是服務器加鎖的,多線程資源共享絕大多數(shù)是在服務器發(fā)生;
  • 提示 : 加鎖是犧牲了性能,保證安全.客戶端的性能不能輕易犧牲

異步下載網絡圖片

  • 在 iOS 開發(fā)中,使用多線程只有一個目的:將耗時操作放在后臺工作舷蟀,待工作完成后汹押,通知主線程更新 UI

  • 耗時的下載操作放在子線程

- (void)viewDidLoad {
    [super viewDidLoad];
    
//    [self loadImageData];
    
    // 在子線程執(zhí)行耗時操作
    [self performSelectorInBackground:@selector(loadImageData) withObject:nil];
}
// 下載圖片的主方法
- (void)loadImageData
{
    // URL
    NSURL *URL = [NSURL URLWithString:@"https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1476696781&di=f721c3cba572282b9d4b135866894858&src=http://www.hn.xinhuanet.com/2016-08/31/1119483302_14726048769591n.jpg"];
    // 發(fā)送網絡請求,獲取圖片二進制數(shù)據(jù),是個耗時操作
    NSData *data = [NSData dataWithContentsOfURL:URL];
    // image : 就是子線程執(zhí)行的結果,需要傳遞到主線程
    UIImage *image = [UIImage imageWithData:data];
    
    // 下載完成之后,通知主線程刷新UI
    // waitUntilDone : 是否等待updateUI執(zhí)行完,再執(zhí)行后面的代碼,一般傳入NO
    [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:NO];
    
    NSLog(@"后面的代碼");
}
  • 更新UI的操作在主線程
// 回到主線程更新UI
- (void)updateUI:(UIImage *)image
{
    self.imgView.image = image;
    [self.imgView sizeToFit];
    self.scrollView.contentSize = image.size;
}
  • 在子線程下載圖片,在主線程更新UI,是線程間通信的一種;
  • 線程間通信 : 一個線程把他執(zhí)行的結果,傳遞到另外的一個線程
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末盏触,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蟆沫,更是在濱河造成了極大的恐慌呻征,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烤礁,死亡現(xiàn)場離奇詭異,居然都是意外死亡肥照,警方通過查閱死者的電腦和手機鸽凶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來建峭,“玉大人,你說我怎么就攤上這事决摧∫谡簦” “怎么了?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵掌桩,是天一觀的道長边锁。 經常有香客問我,道長波岛,這世上最難降的妖魔是什么茅坛? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮则拷,結果婚禮上贡蓖,老公的妹妹穿的比我還像新娘。我一直安慰自己煌茬,他們只是感情好斥铺,可當我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著坛善,像睡著了一般晾蜘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上眠屎,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天剔交,我揣著相機與錄音,去河邊找鬼改衩。 笑死岖常,一個胖子當著我的面吹牛,可吹牛的內容都是我干的燎字。 我是一名探鬼主播腥椒,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼阿宅,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了笼蛛?” 一聲冷哼從身側響起洒放,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎滨砍,沒想到半個月后往湿,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡惋戏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年领追,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片响逢。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡绒窑,死狀恐怖,靈堂內的尸體忽然破棺而出舔亭,到底是詐尸還是另有隱情些膨,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布钦铺,位于F島的核電站订雾,受9級特大地震影響,放射性物質發(fā)生泄漏矛洞。R本人自食惡果不足惜洼哎,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望沼本。 院中可真熱鬧噩峦,春花似錦、人聲如沸擅威。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽郊丛。三九已至李请,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間厉熟,已是汗流浹背导盅。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留揍瑟,地道東北人白翻。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親滤馍。 傳聞我的和親對象是個殘疾皇子岛琼,可洞房花燭夜當晚...
    茶點故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內容