多線程-NSThread

NSThread

每個iOS應用程序都有個專門用來更新顯示UI界面腥放、處理用戶觸摸事件的主線程孙咪,因此不能將其他太耗時的操作放在主線程中執(zhí)行欠拾,不然會造成主線程堵塞

創(chuàng)建一條線程
方式一 動態(tài)方法
    // 1.創(chuàng)建子線程
    /*
     Target: 子線程需要調(diào)用誰的方法
     selector: 被子線程調(diào)用的方法
     object: 調(diào)用方法時, 給方法傳遞的參數(shù)
     */
    // 注意: 如果線程正在執(zhí)行, 那么系統(tǒng)會自動強引用NSThread  當線程中的任務執(zhí)行完畢, 系統(tǒng)會自動釋放線程, 對線程進行一次release操作
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(demo:) object:@"lnj"];
  
    //  給線程取名字
    thread.name = @"子線程1";
    // 設置線程的優(yōu)先級, 取值范圍0.0~1.0, 1.0是最高, 默認就是0.5
    // 注意點: 線程的優(yōu)先級越高, 那么被CPU調(diào)度的可能性就越大  但是并不代表著, 優(yōu)先級高的一定會先執(zhí)行
   
    thread.threadPriority = 0.0;
    // 2.啟動線程    如果通過alloc/init創(chuàng)建NSThread, 那么需要手動啟動線程
    [thread start];
方式二 靜態(tài)方法
/*
     優(yōu)點:
     - 使用簡便
     - 如果通過detach方法創(chuàng)建線程, 不需要手動調(diào)用start啟動線程 \ 系統(tǒng)會自動啟動
     缺點:
     - 不可以進行其它設置
     應用場景:
     - 如果僅僅需要簡單的開啟一個子線程執(zhí)行一些操作, 不需要對子線程進行其它設置, 那么推薦使用detach方法創(chuàng)建線程
     */
    [NSThread detachNewThreadSelector:@selector(demo:) toTarget:self withObject:@"canshu"];
方式三 隱式創(chuàng)建線程
  // 系統(tǒng)會自動在后臺給我們開啟一個子線程, 并且會自動啟動該線程執(zhí)行任務
    [self performSelectorInBackground:@selector(demo:) withObject:@"oooo"];

線程通信

場景:從網(wǎng)絡下載一張圖片酥夭,然后返回主線程更新UI

開啟一個子線程下載圖片

[self performSelectorInBackground:@selector(downlod) withObject:nil];

實現(xiàn)下載圖片方法

- (void)downlod
{
    NSLog(@"%@", [NSThread currentThread]);  //   打印當前線程
    // 1.下載圖片
     NSURL *url = [NSURL URLWithString:@"http://pic.4j4j.cn/upload/pic/20130531/07ed5ea485.jpg"];
     NSData *data = [NSData dataWithContentsOfURL:url];
    // 2.將二進制轉(zhuǎn)換為圖片
    UIImage *image = [UIImage imageWithData:data];  
}

拿到圖片后 返回主線程更新UI 方式一

     /*
     waitUntilDone: 
     YES: 如果傳入YES, 那么會等待updateImage方法執(zhí)行完畢, 才會繼續(xù)執(zhí)行后面的代碼
     NO:  如果傳入NO, 那么不會等待updateImage方法執(zhí)行完畢, 就可以繼續(xù)之后后面的代碼
     */
    // 可以在指定的線程中, 調(diào)用指定對象的指定方法
    [self performSelector:@selector(updateImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES];

拿到圖片后 返回主線程更新UI 方式二 工作中常用

//  這個方法也就不需要再重新實現(xiàn)更新UI的方法了
 [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];

實現(xiàn)更新UI的方法

- (void)updateImage:(UIImage *)image
{
    NSLog(@"%@", [NSThread currentThread]);
    self.imageView.image = image;
}

在當前線程執(zhí)行操作

[self performSelector:@selector(run) withObject:nil]; 

多條線程在同一時間訪問同一塊資源容易出現(xiàn)安全隱患

模擬場景:12306服務器設置了20張從北京到上呵岷冢火車票檐嚣,有三個售票員用他們的電腦進行售票助泽,這里要需要用到互斥鎖 它的作用就是鎖住這塊資源讓它在同一時間只能讓一條線程訪問 接下來先測試加鎖與不加鎖的區(qū)別

創(chuàng)建3條線程代表3個售貨員
- (void)viewDidLoad {
    [super viewDidLoad];
    // 0 初始化票數(shù)
    self.totalCount = 100;
    
    // 1 創(chuàng)建3個售票員
    NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
    thread1.name = @"售票員1";
    self.thread1 = thread1;
    NSThread *thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
    thread2.name = @"售票員2";
    self.thread2 = thread2;
    NSThread *thread3 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
    thread3.name = @"售票員3";
    self.thread3 = thread3;
}
開始售票
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 2.讓3個售票員同事售票
    [self.thread1 start];
    [self.thread2 start];
    [self.thread3 start];
}
售票進行中 不加鎖
- (void)saleTicket
{
    while (1) {
        
        NSLog(@"歡迎光臨");
            // 1.查詢剩余的票數(shù)
            NSUInteger count = self.totalCount;
            // 2.判斷是否還有余票
            if (count > 0) {
                // 線程1   讓線程處于休眠狀態(tài)   模擬售票時間為0.1秒
                [NSThread sleepForTimeInterval:0.1];
                // 2.1賣票
                self.totalCount = count - 1; // 99
                NSLog(@"%@賣了一張票, 還剩%zd票", [NSThread currentThread].name, self.totalCount);
            }else
            {
                // 3.提示客戶, 沒有票了
                NSLog(@"對不起, 沒有票了");
                break;
            }
    }
    
}
看打印結(jié)果

明顯線程沒有獲取到最新的值 造成數(shù)據(jù)訪問錯誤


Paste_Image.png
售票進行中 加鎖
// 售票方法
- (void)saleTicket
{
    while (1) {
        
        NSLog(@"歡迎光臨");
        @synchronized (self) { //@synchronized  為互斥鎖    self可以為任何對象  但必須是同一對象  保證單例
            
            // 1.查詢剩余的票數(shù)
            NSUInteger count = self.totalCount;
            // 2.判斷是否還有余票
            if (count > 0) {
                // 線程1   讓線程處于休眠狀態(tài)   模擬售票時間為0.1秒
                [NSThread sleepForTimeInterval:0.1];
                // 2.1賣票
                self.totalCount = count - 1; // 99
                NSLog(@"%@賣了一張票, 還剩%zd票", [NSThread currentThread].name, self.totalCount);
            }else
            {
                // 3.提示客戶, 沒有票了
                NSLog(@"對不起, 沒有票了");
                break;
            }
        }

    }
    
}
這下就沒有問題了
Paste_Image.png
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市嚎京,隨后出現(xiàn)的幾起案子嗡贺,更是在濱河造成了極大的恐慌诫睬,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辟躏,死亡現(xiàn)場離奇詭異会涎,居然都是意外死亡,警方通過查閱死者的電腦和手機练慕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門劲阎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來龄毡,“玉大人偎捎,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵师幕,是天一觀的道長诬滩。 經(jīng)常有香客問我霹粥,道長,這世上最難降的妖魔是什么疼鸟? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任后控,我火速辦了婚禮,結(jié)果婚禮上空镜,老公的妹妹穿的比我還像新娘浩淘。我一直安慰自己捌朴,他們只是感情好,可當我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布馋袜。 她就那樣靜靜地躺著男旗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪欣鳖。 梳的紋絲不亂的頭發(fā)上察皇,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天,我揣著相機與錄音泽台,去河邊找鬼什荣。 笑死,一個胖子當著我的面吹牛怀酷,可吹牛的內(nèi)容都是我干的稻爬。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蜕依,長吁一口氣:“原來是場噩夢啊……” “哼桅锄!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起样眠,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤友瘤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后檐束,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辫秧,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年被丧,在試婚紗的時候發(fā)現(xiàn)自己被綠了盟戏。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡甥桂,死狀恐怖柿究,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情黄选,我是刑警寧澤笛求,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站糕簿,受9級特大地震影響探入,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜懂诗,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一蜂嗽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧殃恒,春花似錦植旧、人聲如沸辱揭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽问窃。三九已至,卻和暖如春完沪,著一層夾襖步出監(jiān)牢的瞬間域庇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工覆积, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留听皿,地道東北人。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓宽档,卻偏偏與公主長得像尉姨,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子吗冤,可洞房花燭夜當晚...
    茶點故事閱讀 44,689評論 2 354

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