掃盲——>iOS中の多線程

今天被人問到了下多線程方面的一些知識(shí),平時(shí)一直在用然后原 理不是理解得很透徹,所以今晚決定整理資料來個(gè)掃盲貼.開始前我們先來個(gè)基礎(chǔ)知識(shí)講解吧.

![Uploading 多線程_837987.jpg . . .]

首先開始我們先區(qū)別下進(jìn)程與線程的區(qū)別.
***
進(jìn)程:系統(tǒng)每個(gè)程序運(yùn)行都需要一個(gè)進(jìn)程,進(jìn)程間是在其專用且

受保護(hù)的內(nèi)存空間內(nèi)獨(dú)立的
線程:1)線程為進(jìn)程能夠正常運(yùn)作提供了條件,且每個(gè)進(jìn)程最少得一條線程.
2)所謂進(jìn)程通俗講就是我們系統(tǒng)運(yùn)行的程序,進(jìn)程的基本執(zhí)行單元為線程.

線程串行:
     在單線程中執(zhí)行任務(wù)是需要排隊(duì)的,你如果要執(zhí)行多人任務(wù),那么就只能按順序執(zhí)行這些任務(wù);就像去超市排隊(duì)結(jié)賬,你要等別  人結(jié)賬完才能輪到你

多線程

廢話不多說先來了解下什么是多線程先
***基本概念***
多線程就是給單前的進(jìn)程(APP/程序)開多條線程就是開幾條水管好排水,每條水管執(zhí)行不同的Task.
***線程的并行***
所謂并行就是你像燒水的時(shí)候可以順便干點(diǎn)其它東西,大家互相互執(zhí)行不同的東西
說白了就是你的CPU在多線線程中來回工作,就是這條線程干點(diǎn)那條線程干點(diǎn)
***多線程優(yōu)點(diǎn)與缺點(diǎn) ***
缺點(diǎn):1)開多線程就是一個(gè)人在進(jìn)行多個(gè)任務(wù)一樣,這樣CPU開銷會(huì)很大,太多線程其實(shí)會(huì)影響性能的
2)這樣程序會(huì)設(shè)計(jì)的比較復(fù)雜,在數(shù)據(jù)共享與線程(APP)間通信實(shí)現(xiàn)難度很大
3)加重內(nèi)存開銷(默認(rèn)主線程是1M,子線程是512KB)

優(yōu)點(diǎn):1)目前CPU的處理效率很高都是多核多核一定程度上提高資源的利用率(內(nèi)存/CPU)
     2)提高程序執(zhí)行的效率了,就是你燒開水去切菜一樣提高效率節(jié)省時(shí)間.

在iOS開發(fā)中的用處

寶貝說再好還不如來來點(diǎn)實(shí)在的對(duì)吧.
a)主線程
1.一個(gè)APP運(yùn)行后在iOS系統(tǒng)中默認(rèn)就是在主線程中運(yùn)行的我們把它稱為"主線程"或者"UI線程"
2.刷新顯示界面,處理用戶交互事件

坑點(diǎn)!!!:1)如果是在對(duì)一些比較占用資源運(yùn)行時(shí)間較長的耗時(shí)操作記住要開子線程,要不你的APP就卡死啦
2)和用戶交互的刷新操作一定要放在主線程,要不一些執(zhí)著的用戶會(huì)以為貴公司APP垃圾辣雞就卸了.寶寶心里苦

主題幾種多線程實(shí)現(xiàn)方案

***程序員管理的生命***
pthread說明:惡心的C語言API,我就不想用了,用起來好難,線程的生死還要我們程序員覺得,一不小心就崩了程序崩了知道不.
特點(diǎn):1)可用在Unix\Linux\Windows主流系統(tǒng)可以跨平臺(tái)開發(fā)
     2)通用的API就是大家都可以用,公共廁所

NSThread特點(diǎn):1)這個(gè)東西我們偶爾使用
             2)偉大的OOP類
             3)還是得碼農(nóng)解決生死

***系統(tǒng)自動(dòng)管理***
GCD特點(diǎn):1)為了替代NSThread等需要人工判斷生死的東西
        2)為了不浪費(fèi)多核的CPU資源
        3)還是C語言,使用難道大大的難

NSOperation特點(diǎn):1)OOP語言,系統(tǒng)會(huì)自動(dòng)管理
                2)基于GCD底層的,比GCD使用方便還新添一些簡單的功能

重點(diǎn)了解OOP語言中的NSTHread

基本使用:創(chuàng)建的3種方式
1)自動(dòng)啟動(dòng),不能管理內(nèi)容設(shè)置
[self performSelectorInBackground:@selector(run:) withObject:@"I am 后臺(tái)線程"];
2)自動(dòng)啟動(dòng),分離出一條子線程,還是不能管理內(nèi)容設(shè)置
[NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"我是分離出來的子線程"];
***推薦使用***
3)可以管理內(nèi)容設(shè)置但是需要手動(dòng)開啟線程.
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(run:) object:@"wendingding"];
         //啟動(dòng)線程
        [thread start];

其它一些屬性使用:
                1)屬性名稱:thread.name = @"快給我起名字";
                2)優(yōu)先級(jí)(默認(rèn)0.5):thread.threadPriority = 1.0;

線程safety:1)多線程同時(shí)操作同一個(gè)數(shù)據(jù)會(huì)發(fā)生死鎖情況,需要加互斥所,相關(guān)代碼@synchronized(self){}
2)原子性與非原子屬性(是否對(duì)setter方法加鎖), 線程同步與同步線程區(qū)別
線程同步:多個(gè)線程操作同一個(gè)數(shù)據(jù)資源提供競爭的解決方案
同步線程:就是排隊(duì)串行執(zhí)行任務(wù)的線程

線程狀態(tài):[NSThread  exit]//退出當(dāng)前的線程
         [NSThread sleepForTimeInterval:2.0];
         [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];
         //:線程掛了是不能復(fù)生的

線程間通信:
 -(void)touchesBegan:(nonnull NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event
    {
    //    [self download2];

        //開啟一條子線程來下載圖片
        [NSThread detachNewThreadSelector:@selector(downloadImage) toTarget:self withObject:nil];
    }

    -(void)downloadImage
    {
        //1.確定要下載網(wǎng)絡(luò)圖片的url地址,一個(gè)url唯一對(duì)應(yīng)著網(wǎng)絡(luò)上的一個(gè)資源
        NSURL *url = [NSURL URLWithString:@"http://www.reibang.com/p/e09c44c5ab12"];

        //2.根據(jù)url地址下載圖片數(shù)據(jù)到本地(二進(jìn)制數(shù)據(jù)
        NSData *data = [NSData dataWithContentsOfURL:url];

        //3.把下載到本地的二進(jìn)制數(shù)據(jù)轉(zhuǎn)換成圖片
        UIImage *image = [UIImage imageWithData:data];

        //4.回到主線程刷新UI
        //4.1 第一種方式
    //    [self performSelectorOnMainThread:@selector(showImage:) withObject:image waitUntilDone:YES];

        //4.2 第二種方式
    //    [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];

        //4.3 第三種方式
        [self.imageView performSelector:@selector(setImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES];
    }

計(jì)算代碼時(shí)間:
1)CFTimeInterval start = CFAbsoluteTimeGetCurrent();
        NSData *data = [NSData dataWithContentsOfURL:url];

        CFTimeInterval end = CFAbsoluteTimeGetCurrent();
        NSLog(@"操作花費(fèi)的時(shí)間為%f",end - start);
2)NSDate *start = [NSDate date];
        //2.根據(jù)url地址下載圖片數(shù)據(jù)到本地(二進(jìn)制數(shù)據(jù))
        NSData *data = [NSData dataWithContentsOfURL:url];

        NSDate *end = [NSDate date];
        NSLog(@"第二步操作花費(fèi)的時(shí)間為%f",[end timeIntervalSinceDate:start]);

學(xué)習(xí)重點(diǎn) GCD

基本知識(shí):
1)同步/異步函數(shù)
2)隊(duì)列/任務(wù)理解

使用重點(diǎn):
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í)行順序上面的差異

GCD中線程間通信:

  //0.獲取一個(gè)全局的隊(duì)列
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

    //1.先開啟一個(gè)線程获黔,把下載圖片的操作放在子線程中處理
    dispatch_async(queue, ^{

       //2.下載圖片
        NSURL *url = [NSURL URLWithString:@"http://www.baidu.jpg"];
        NSData *data = [NSData dataWithContentsOfURL:url];
        UIImage *image = [UIImage imageWithData:data];

        NSLog(@"下載操作所在的線程--%@",[NSThread currentThread]);

        //3.回到主線程刷新UI
        dispatch_async(dispatch_get_main_queue(), ^{
           self.imageView.image = image;
           //打印查看當(dāng)前線程
            NSLog(@"刷新UI---%@",[NSThread currentThread]);
        });

    });

GCD中其它法寶

1)柵欄函數(shù)(控制任務(wù)的執(zhí)行順序)
    dispatch_barrier_async(queue, ^{
        NSLog(@"柵欄函數(shù)");
    });

2)延遲執(zhí)行(延遲·控制在哪個(gè)線程執(zhí)行)
      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"---%@",[NSThread currentThread]);
    });

3)一次性代碼(注意不能放到懶加載)
    -(void)onceToken
    {
        //整個(gè)程序運(yùn)行過程中只會(huì)執(zhí)行一次
        //onceToken用來記錄該部分的代碼是否被執(zhí)行過
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{

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

4)快速迭代(開多個(gè)線程并發(fā)完成迭代操作)
       dispatch_apply(subpaths.count, queue, ^(size_t index) {
    });

5)隊(duì)列組(同柵欄函數(shù))
    //創(chuàng)建隊(duì)列組
    dispatch_group_t group = dispatch_group_create();
    //隊(duì)列組中的任務(wù)執(zhí)行完畢之后蚀苛,執(zhí)行該函數(shù)
    dispatch_group_notify(dispatch_group_t group,dispatch_queue_t queue,dispatch_block_t block);

6)進(jìn)入群組和離開群組
    dispatch_group_enter(group);//執(zhí)行該函數(shù)后,后面異步執(zhí)行的block會(huì)被gruop監(jiān)聽
    dispatch_group_leave(group);//異步block中玷氏,所有的任務(wù)都執(zhí)行完畢堵未,最后離開群組
    //注意:dispatch_group_enter|dispatch_group_leave必須成對(duì)使用
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市预茄,隨后出現(xiàn)的幾起案子兴溜,更是在濱河造成了極大的恐慌,老刑警劉巖耻陕,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拙徽,死亡現(xiàn)場離奇詭異,居然都是意外死亡诗宣,警方通過查閱死者的電腦和手機(jī)膘怕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來召庞,“玉大人岛心,你說我怎么就攤上這事±鹤疲” “怎么了忘古?”我有些...
    開封第一講書人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長诅诱。 經(jīng)常有香客問我髓堪,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任干旁,我火速辦了婚禮驶沼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘争群。我一直安慰自己回怜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開白布换薄。 她就那樣靜靜地躺著玉雾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪专控。 梳的紋絲不亂的頭發(fā)上抹凳,一...
    開封第一講書人閱讀 49,730評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音伦腐,去河邊找鬼。 笑死失都,一個(gè)胖子當(dāng)著我的面吹牛柏蘑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播粹庞,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼咳焚,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了庞溜?” 一聲冷哼從身側(cè)響起革半,我...
    開封第一講書人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎流码,沒想到半個(gè)月后又官,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡漫试,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年六敬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片驾荣。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡外构,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出播掷,到底是詐尸還是另有隱情审编,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布歧匈,位于F島的核電站垒酬,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜伤溉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一般码、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧乱顾,春花似錦板祝、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至伏伯,卻和暖如春橘洞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背说搅。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來泰國打工炸枣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人弄唧。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓适肠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親候引。 傳聞我的和親對(duì)象是個(gè)殘疾皇子侯养,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

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

  • Object C中創(chuàng)建線程的方法是什么?如果在主線程中執(zhí)行代碼澄干,方法是什么逛揩?如果想延時(shí)執(zhí)行代碼、方法又是什么麸俘? 1...
    AlanGe閱讀 1,721評(píng)論 0 17
  • .一.進(jìn)程 進(jìn)程:是指在系統(tǒng)中正在運(yùn)行的一個(gè)應(yīng)用程序,每個(gè)進(jìn)程之間是獨(dú)立的辩稽,每個(gè)進(jìn)程均運(yùn)行在其專用且受保護(hù)的內(nèi)存空...
    IIronMan閱讀 4,479評(píng)論 1 33
  • 本文選譯自《Threading Programming Guide》。 導(dǎo)語 線程技術(shù)作為在單個(gè)應(yīng)用程序中并發(fā)執(zhí)行...
    巧巧的二表哥閱讀 2,421評(píng)論 4 24
  • 目錄 [創(chuàng)建與維護(hù)](# 1)創(chuàng)建并設(shè)置一個(gè)私有的Spec Repo創(chuàng)建PodLib創(chuàng)建lib所對(duì)應(yīng)的podspe...
    水在玩焱閱讀 8,289評(píng)論 1 10
  • 夫天地者疾掰,萬物之逆旅搂誉。 光陰者,百代之過客静檬。 而浮生若夢(mèng)炭懊,為歡幾何? 浮生六記得名于李白這首充滿感傷的小序拂檩,初得此...
    追求自由的小五閱讀 350評(píng)論 1 4