多線程之NSThread

Pthread

使用pthread必須盜用頭文件#import <pthread.h>

可以使用[NSThread currentThread]來(lái)獲取當(dāng)前在哪條線程上面 num = 1為主線程

創(chuàng)建線程

pthread_t myRestrict;
pthread_create(&myRestrict, NULL, run, NULL);run為一個(gè)void的函數(shù)

NSThread

主線程相關(guān)用法

+ (NSThread *)mainThread; // 獲得主線程
- (BOOL)isMainThread; // 是否為主線程
+ (BOOL)isMainThread; // 是否為主線程

其他用法

//獲得當(dāng)前線程
NSThread *current = [NSThread currentThread];
//線程的名字
- (void)setName:(NSString *)n;
- (NSString *)name;

創(chuàng)建線程

  1. 第一種方式

     NSThread *thread = [NSThread alloc]initWithTarget:self selector:@selector(download:) object:@"哈哈"];//創(chuàng)建一個(gè)線程去調(diào)用download:方法并把哈哈傳給這個(gè)方法,也可以不傳值乌奇,設(shè)置為nil即可
     thread.name = @"下載線程";//可以設(shè)置線程的名稱则披,設(shè)置與否不會(huì)造成什么影響的
     [thread start];//啟動(dòng)線程蓖墅,必須加上儒飒,不然無(wú)法開(kāi)啟線程
    
  2. 第二種方式

     [NSThread detachNewThreadSelector:@selector(download:) toTarget:self withObject:@"http://a.jpg"];
    
  3. 第三種方式(隱式創(chuàng)建)

     [self performSelectorInBackground:@selector(download:) withObject:@"http://c.gif"];
     [self performSelector:@selector(download:) withObject:@"http://c.gif"];(不會(huì)開(kāi)辟新線程)
     [self download:@"http://c.gif"];(不會(huì)開(kāi)辟新線程)
    

第二種和第三種創(chuàng)建的優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn):簡(jiǎn)單快捷
  • 缺點(diǎn):無(wú)法對(duì)線程進(jìn)行更詳細(xì)的設(shè)置

自定義NSThread

當(dāng)我們想監(jiān)聽(tīng)NSThread是否被釋放以及我們想自己搞一個(gè)自己Thread眼姐,這時(shí)候我們可以繼承自NSThread實(shí)現(xiàn)自己的Thread,有一個(gè)方法是需要實(shí)現(xiàn)的赏迟,main這個(gè)方法屡贺,我們需要做的事情可以放到這里面

線程狀態(tài)

一般來(lái)說(shuō)有以下幾種

  1. 新建NEW
  2. 就緒Runnable
  3. 運(yùn)行Running
  4. 阻塞Blocked
  5. 死亡Dead

狀態(tài)之間的切換見(jiàn)下圖所示:

屏幕快照 2016-05-20 上午10.26.08.png

CPU在同一時(shí)間內(nèi)只能執(zhí)行一條多線程,并發(fā)是CPU調(diào)度任務(wù)才會(huì)造成多線程是同時(shí)執(zhí)行的(因?yàn)檎{(diào)度事件非常短)

控制線程的狀態(tài)

//啟動(dòng)線程
- (void)start; 
// 進(jìn)入就緒狀態(tài) -> 運(yùn)行狀態(tài)锌杀。當(dāng)線程任務(wù)執(zhí)行完畢甩栈,自動(dòng)進(jìn)入死亡狀態(tài)

//阻塞(暫停)線程
+ (void)sleepUntilDate:(NSDate *)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
// 進(jìn)入阻塞狀態(tài)

//強(qiáng)制停止線程
+ (void)exit;
// 進(jìn)入死亡狀態(tài)

注意:一旦線程停止(死亡)了,就不能再次開(kāi)啟任務(wù)

多線程的安全隱患

  • 資源共享
  • 1塊資源可能會(huì)被多個(gè)線程共享糕再,也就是多個(gè)線程可能會(huì)訪問(wèn)同一塊資源
  • 比如多個(gè)線程訪問(wèn)同一個(gè)對(duì)象量没、同一個(gè)變量、同一個(gè)文件
  • 當(dāng)多個(gè)線程訪問(wèn)同一塊資源時(shí)突想,很容易引發(fā)數(shù)據(jù)錯(cuò)亂和數(shù)據(jù)安全問(wèn)題(現(xiàn)實(shí)生活中有買車票和銀行存取錢等)
    存錢取錢殴蹄,內(nèi)容見(jiàn)下圖
屏幕快照 2016-05-20 上午10.39.41.png

網(wǎng)上用的最多的一張圖

無(wú)標(biāo)題.png

互斥鎖(@synchronized)

互斥鎖.png

  • 互斥鎖使用格式
    @synchronized(鎖對(duì)象) { // 需要鎖定的代碼  }
    注意:鎖定1份代碼只用1把鎖,用多把鎖是無(wú)效的
  • 互斥鎖的優(yōu)缺點(diǎn)
  • 優(yōu)點(diǎn):能有效防止因多線程搶奪資源造成的數(shù)據(jù)安全問(wèn)題
  • 缺點(diǎn):需要消耗大量的CPU資源
  • 互斥鎖使用前提是多條線程搶奪同一塊資源
  • 相關(guān)專業(yè)術(shù)語(yǔ):線程同步
  • 線程同步的意思是:多條線程在同一條線上執(zhí)行(按順序地執(zhí)行任務(wù))
  • 互斥鎖猾担,就是使用了線程同步技術(shù)

火車票以及銀行取錢等情況下需要使用互斥鎖來(lái)對(duì)線程進(jìn)行加鎖袭灯,避免造成混亂等情況
比如三個(gè)人進(jìn)行買火車票,如果不用互斥鎖的話那么一張票可能被兩個(gè)人或者三個(gè)人同時(shí)買到绑嘹,顯然這是不符合邏輯的稽荧,每張票只能允許同一個(gè)人購(gòu)買。這時(shí)候就需要用到互斥鎖來(lái)對(duì)火車票進(jìn)行加鎖了工腋,如果某一張火車票被人購(gòu)買了姨丈,那么別人就無(wú)法繼續(xù)買這張火車票了。

- (void)saleTicket
{
    while (1) {
        // ()小括號(hào)里面放的是鎖對(duì)象(一般self即可擅腰,不要重復(fù)生成對(duì)象)
        @synchronized(self) { // 開(kāi)始加鎖
            int count = self.leftTicketCount;
            if (count > 0) {
                [NSThread sleepForTimeInterval:0.05];
            
                self.leftTicketCount = count - 1;
            
                NSLog(@"%@賣了一張票, 剩余%d張票", [NSThread currentThread].name, self.leftTicketCount);
            } else {
                return; // 退出循環(huán)
            }
        } // 解鎖
    }
}

原子和非原子屬性

  • OC在定義屬性時(shí)有nonatomic和atomic兩種選擇
  • atomic:原子屬性蟋恬,為setter方法加鎖(默認(rèn)就是atomic)
  • nonatomic:非原子屬性,不會(huì)為setter方法加鎖趁冈,一般都用nonatomic歼争,這樣性能會(huì)稍微好點(diǎn)
  • nonatomic和atomic對(duì)比
    • atomic:線程安全,需要消耗大量的資源
    • nonatomic:非線程安全渗勘,適合內(nèi)存小的移動(dòng)設(shè)備
  • iOS開(kāi)發(fā)的建議
  • 所有屬性都聲明為nonatomic
  • 盡量避免多線程搶奪同一塊資源
  • 盡量將加鎖矾飞、資源搶奪的業(yè)務(wù)邏輯交給服務(wù)器端處理,減小移動(dòng)客戶端的壓力

線程間通信

  • 什么叫做線程間通信
  • 在1個(gè)進(jìn)程中呀邢,線程往往不是孤立存在的,多個(gè)線程之間需要經(jīng)常進(jìn)行通信
  • 線程間通信的體現(xiàn)
  • 1個(gè)線程傳遞數(shù)據(jù)給另1個(gè)線程
  • 在1個(gè)線程中執(zhí)行完特定任務(wù)后豹绪,轉(zhuǎn)到另1個(gè)線程繼續(xù)執(zhí)行任務(wù)

當(dāng)處理耗時(shí)操作的時(shí)候需要開(kāi)辟一條線程价淌,比如從網(wǎng)絡(luò)上面請(qǐng)求數(shù)據(jù)的時(shí)候申眼,網(wǎng)絡(luò)請(qǐng)求應(yīng)該新開(kāi)辟一條線程,放到子線程里面去蝉衣,然后下載完成之后通知主線程進(jìn)行更新UI括尸。(這樣也是為了線程安全著想)

    [self performSelectorOnMainThread:@selector(downloadFinished:) withObject:image waitUntilDone:NO];//回到主線程

比如在子線程中進(jìn)行網(wǎng)絡(luò)請(qǐng)求,得到數(shù)據(jù)之后通知主線程更新UI病毡,具體代碼如下


- (void)downImage {
    
    NSURL *url = [NSURL URLWithString:@"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg"];
    NSData *data = [NSData dataWithContentsOfURL:url];
    UIImage *image = [UIImage imageWithData:data];
    
//    [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];
    
    [self.imageView performSelector:@selector(setImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES];
//    [self performSelectorOnMainThread:@selector(hehe:) withObject:image waitUntilDone:YES];
}

- (void)hehe:(UIImage *)image
{
    self.imageView.image = image;
}

小結(jié)

  1. -(id)init //這個(gè)方法是NSThread的指定初始化方法
  2. -(id)initWithTarget:(id)target selector:(SEL)seletoc object:(id)argument//初始化一個(gè)線程濒翻,應(yīng)該注意到這個(gè)SEL方法只能有一個(gè)參數(shù),并且選擇的方法不能有返回值啦膜,而且這個(gè)方法只是創(chuàng)建了一個(gè)線程有送,并沒(méi)有開(kāi)始這個(gè)線程,需要調(diào)用start方法開(kāi)始線程
  3. +(void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument//創(chuàng)建并開(kāi)始一個(gè)線程
  4. -(void)start//開(kāi)始一個(gè)線程
  5. +(void)sleepUntilDate:(NSDate *)aDate//阻塞當(dāng)前線程僧家,直到指定時(shí)間
  6. +(void)sleepForTimeInterval:(NSTimeInterval)time//使線程睡眠一段時(shí)間
  7. -(BOOL)isExecuting//判斷線程是否正在執(zhí)行
  8. -(BOOL)isCancelled//判斷線程是否已經(jīng)取消
  9. -(BOOL)isFinished//判斷線程是否執(zhí)行完
  10. +(BOOL)isMainThread//判斷當(dāng)前線程是否是主線程
  11. +(BOOL)isMultiThreaded//判斷是否是多線程的
  12. +(NSThread *)currentThread//返回當(dāng)前線程
  13. +(NSThread *)mainThread//返回主線程對(duì)象
  14. +(NSArray *)callStackReturnAddresses//返回的是這個(gè)線程在棧中所占的地址所組成的數(shù)組
  15. +(NSArray *)callStackSymbols//返回椚刚空間的符號(hào)
  16. – threadDictionary //返回線程對(duì)象的字典
  17. – name //返回線程名字
  18. – setName: //設(shè)置線程名字
  19. – stackSize //返回線程所占棧的空間大小
  20. – setStackSize: //設(shè)置線程所占棧的空間大小
  21. +threadPriority //返回當(dāng)前線程的優(yōu)先權(quán),其實(shí)返回的是一個(gè)double型數(shù)字八拱,
    //從0.0 到1.0 其中1.0最高
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末阵赠,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子肌稻,更是在濱河造成了極大的恐慌清蚀,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件爹谭,死亡現(xiàn)場(chǎng)離奇詭異枷邪,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)旦棉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門齿风,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人绑洛,你說(shuō)我怎么就攤上這事救斑。” “怎么了真屯?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵脸候,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我绑蔫,道長(zhǎng)运沦,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任配深,我火速辦了婚禮携添,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘篓叶。我一直安慰自己烈掠,他們只是感情好羞秤,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著左敌,像睡著了一般瘾蛋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上矫限,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天哺哼,我揣著相機(jī)與錄音,去河邊找鬼叼风。 笑死取董,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的咬扇。 我是一名探鬼主播甲葬,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼懈贺!你這毒婦竟也來(lái)了经窖?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤梭灿,失蹤者是張志新(化名)和其女友劉穎画侣,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體堡妒,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡配乱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了皮迟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搬泥。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖伏尼,靈堂內(nèi)的尸體忽然破棺而出忿檩,到底是詐尸還是另有隱情,我是刑警寧澤爆阶,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布燥透,位于F島的核電站,受9級(jí)特大地震影響辨图,放射性物質(zhì)發(fā)生泄漏班套。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一故河、第九天 我趴在偏房一處隱蔽的房頂上張望吱韭。 院中可真熱鬧,春花似錦鱼的、人聲如沸理盆。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)熏挎。三九已至,卻和暖如春晌砾,著一層夾襖步出監(jiān)牢的瞬間坎拐,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工养匈, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留哼勇,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓呕乎,卻偏偏與公主長(zhǎng)得像积担,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子猬仁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

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

  • 1帝璧、簡(jiǎn)介:1.1 iOS有三種多線程編程的技術(shù),分別是:1.湿刽、NSThread2的烁、Cocoa NSOperatio...
    LuckTime閱讀 1,335評(píng)論 0 1
  • NSThread 優(yōu)點(diǎn):輕量級(jí)的,面向?qū)ο蟮木€程技術(shù)诈闺,可以直接操作線程對(duì)象 缺點(diǎn):需要程序員管理生命周期渴庆,線程同步...
    錦瑟流年終成憶閱讀 232評(píng)論 0 1
  • iOS多線程開(kāi)發(fā)基礎(chǔ)概念 進(jìn)程 VS 線程 進(jìn)程:程序的一次執(zhí)行,是正在執(zhí)行的程序的實(shí)例雅镊,它是Unix的一個(gè)基本概...
    qingmarch閱讀 360評(píng)論 0 1
  • 衛(wèi)生間的排風(fēng)絲絲作響像電流汗液在身體里登臺(tái)我坐著抽了一支煙濕了全身——2017-06-19
    小者閱讀 159評(píng)論 0 1
  • 7 《士兵突擊》第七集中襟雷,被天上掉下的餡餅給砸暈了的許三多雖然舍不得離開(kāi)五班,但還是被好心的班長(zhǎng)和戰(zhàn)友押送到了團(tuán)部...
    筱昀閱讀 1,119評(píng)論 5 12