【多線程】NSThread

1??創(chuàng)建和啟動線程簡單說明

一個(gè)NSThread對象就代表一條線程

創(chuàng)建、啟動線程
 NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[thread start];
// 線程一啟動秦效,就會在線程thread中執(zhí)行self的run方法
主線程相關(guān)用法
+ (NSThread *)mainThread; // 獲得主線程
- (BOOL)isMainThread; // 是否為主線程
+ (BOOL)isMainThread; // 是否為主線程
其他用法
//獲得當(dāng)前線程
NSThread *current = [NSThread currentThread];
//線程的調(diào)度優(yōu)先級:調(diào)度優(yōu)先級的取值范圍是0.0 ~ 1.0,默認(rèn)0.5捅膘,值越大郁惜,優(yōu)先級越高
+ (double)threadPriority;
+ (BOOL)setThreadPriority:(double)p;
//設(shè)置線程的名字
- (void)setName:(NSString *)n;
- (NSString *)name;

創(chuàng)建線程后自動啟動線程

[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
//  隱式創(chuàng)建并啟動線程  
[self performSelectorInBackground:@selector(run) withObject:nil];
//上述2種創(chuàng)建線程方式的優(yōu)缺點(diǎn)
//優(yōu)點(diǎn):簡單快捷
//缺點(diǎn):無法對線程進(jìn)行更詳細(xì)的設(shè)置

2??線程安全

一、多線程的安全隱患

資源共享

  • 1塊資源可能會被多個(gè)線程共享趾断,也就是多個(gè)線程可能會訪問同一塊資源
  • 比如多個(gè)線程訪問同一個(gè)對象、同一個(gè)變量吩愧、同一個(gè)文件
  • 當(dāng)多個(gè)線程訪問同一塊資源時(shí)芋酌,很容易引發(fā)數(shù)據(jù)錯亂和數(shù)據(jù)安全問題

示例一:

示例二:

問題代碼:

#import "YYViewController.h"
11 
12 @interface YYViewController ()
13 //剩余票數(shù)
14 
15 @property(nonatomic,assign) int leftTicketsCount;
16 @property(nonatomic,strong)NSThread *thread1;
17 @property(nonatomic,strong)NSThread *thread2;
18 @property(nonatomic,strong)NSThread *thread3;
19 
20 
21 @end
22 
23 
24 @implementation YYViewController
25 
26 
27 - (void)viewDidLoad
28 {
29     [super viewDidLoad];
30 
31     //默認(rèn)有20張票
32 
33     self.leftTicketsCount=10;
34 
35     //開啟多個(gè)線程,模擬售票員售票
36 
37     self.thread1=[[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil];
38 
39     self.thread1.name=@"售票員A";
40 
41     self.thread2=[[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil];
42 
43     self.thread2.name=@"售票員B";
44 
45     self.thread3=[[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil];
46     self.thread3.name=@"售票員C";
47 }
48 
49  
50 -(void)sellTickets
51 {
52     while (1) {
53         //1.先檢查票數(shù)
54         int count=self.leftTicketsCount;
55         if (count>0) {
56             //暫停一段時(shí)間
57             [NSThread sleepForTimeInterval:0.002];
58 
59             //2.票數(shù)-1
60            self.leftTicketsCount= count-1;
61  
62             //獲取當(dāng)前線程
63             NSThread *current=[NSThread currentThread];
64             NSLog(@"%@--賣了一張票雁佳,還剩余%d張票",current,self.leftTicketsCount);
65         }else
66         {
67             //退出線程
68             [NSThread exit];
69         }
70     }
71 }
72 
73 
74 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
75 { 
76     //開啟線程
77 
78    [self.thread1 start];
79     [self.thread2 start];
80     [self.thread3 start];
81 
82 }
83 
84 @end

打印結(jié)果:

image
二脐帝、安全隱患分析
三、如何解決
  • 互斥鎖使用格式
  • @synchronized(鎖對象) { // 需要鎖定的代碼 }
  • 注意:鎖定1份代碼只用1把鎖糖权,用多把鎖是無效的
43 -(void)sellTickets
44 {
45     while (1) {
46         @synchronized(self){//只能加一把鎖
47         //1.先檢查票數(shù)
48 
49         int count=self.leftTicketsCount;
50         if (count>0) {
51             //暫停一段時(shí)間
52             [NSThread sleepForTimeInterval:0.002];
53             //2.票數(shù)-1
54 
55            self.leftTicketsCount= count-1;
56             //獲取當(dāng)前線程
57             NSThread *current=[NSThread currentThread];
58             NSLog(@"%@--賣了一張票堵腹,還剩余%d張票",current,self.leftTicketsCount);
59 
60         }else
61         {
62             //退出線程
63             [NSThread exit];
64         }
65         }
66     }
67 }

執(zhí)行效果圖


互斥鎖的優(yōu)缺點(diǎn)
  • 優(yōu)點(diǎn):能有效防止因多線程搶奪資源造成的數(shù)據(jù)安全問題
  • 缺點(diǎn):需要消耗大量的CPU資源
  • 互斥鎖的使用前提:多條線程搶奪同一塊資源
  • 相關(guān)專業(yè)術(shù)語:線程同步,多條線程按順序地執(zhí)行任務(wù)
  • 互斥鎖,就是使用了線程同步技術(shù)
四:原子和非原子屬性
  • OC在定義屬性時(shí)有nonatomic和atomic兩種選擇
  • atomic:原子屬性星澳,為setter方法加鎖(默認(rèn)就是atomic)
  • nonatomic:非原子屬性秸滴,不會為setter方法加鎖
  • atomic加鎖原理
1 @property (assign, atomic) int age;
2 
3 - (void)setAge:(int)age
4 { 
5 
6     @synchronized(self) { 
7        _age = age;
8     }
9 }
原子和非原子屬性的選擇
  • nonatomic和atomic對比
  • atomic:線程安全,需要消耗大量的資源
  • nonatomic:非線程安全募判,適合內(nèi)存小的移動設(shè)備
iOS開發(fā)的建議
  • 所有屬性都聲明為nonatomic
  • 盡量避免多線程搶奪同一塊資源
  • 盡量將加鎖荡含、資源搶奪的業(yè)務(wù)邏輯交給服務(wù)器端處理,減小移動客戶端的壓力

3??線程間通信

線程間通信:在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ù)

線程間通信常用方法

  • (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;

  • (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;

線程間通信示例 – 圖片下載

12 @interface YYViewController ()
13 @property (weak, nonatomic) IBOutlet UIImageView *iconView;
14 @end
15 
16 @implementation YYViewController
17 
18 - (void)viewDidLoad
19 {
20     [super viewDidLoad];
21 }
22 
23  
24 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
25 {
26 // 在子線程中調(diào)用download方法下載圖片
27 
28     [self performSelectorInBackground:@selector(download) withObject:nil];
29 }
30 
31  
32 -(void)download
33 {
34 
35     //1.根據(jù)URL下載圖片
36     //從網(wǎng)絡(luò)中下載圖片
37     NSURL *urlstr=[NSURL URLWithString:@"fdsf"];
38 
39     //把圖片轉(zhuǎn)換為二進(jìn)制的數(shù)據(jù)
40     NSData *data=[NSData dataWithContentsOfURL:urlstr];//這一行操作會比較耗時(shí)
41 
42     //把數(shù)據(jù)轉(zhuǎn)換成圖片
43     UIImage *image=[UIImage imageWithData:data];
44 
45     //2.回到主線程中設(shè)置圖片
46     //第一種方式
47 //    [self performSelectorOnMainThread:@selector(settingImage:) withObject:image waitUntilDone:NO];
48 
49     //第二種方式
50     //    [self.imageView performSelector:@selector(setImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:NO];
51 
52     //第三種方式
53    [self.iconView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];
54 }
55 
56 
57 //設(shè)置顯示圖片
58 //-(void)settingImage:(UIImage *)image
59 //{
60 //    self.iconView.image=image;
61 //}
62 
63 @end

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末装处,一起剝皮案震驚了整個(gè)濱河市误债,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌妄迁,老刑警劉巖寝蹈,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異登淘,居然都是意外死亡箫老,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進(jìn)店門黔州,熙熙樓的掌柜王于貴愁眉苦臉地迎上來耍鬓,“玉大人,你說我怎么就攤上這事流妻∩瘢” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵绅这,是天一觀的道長涣达。 經(jīng)常有香客問我,道長证薇,這世上最難降的妖魔是什么度苔? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮棕叫,結(jié)果婚禮上林螃,老公的妹妹穿的比我還像新娘。我一直安慰自己俺泣,他們只是感情好疗认,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著伏钠,像睡著了一般横漏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上熟掂,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天缎浇,我揣著相機(jī)與錄音,去河邊找鬼赴肚。 笑死素跺,一個(gè)胖子當(dāng)著我的面吹牛二蓝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播指厌,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼刊愚,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了踩验?” 一聲冷哼從身側(cè)響起鸥诽,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎箕憾,沒想到半個(gè)月后牡借,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡袭异,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年钠龙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扁远。...
    茶點(diǎn)故事閱讀 40,030評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡俊鱼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出畅买,到底是詐尸還是另有隱情并闲,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布谷羞,位于F島的核電站帝火,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏湃缎。R本人自食惡果不足惜犀填,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望嗓违。 院中可真熱鬧九巡,春花似錦、人聲如沸蹂季。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽偿洁。三九已至撒汉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間涕滋,已是汗流浹背睬辐。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人溯饵。 一個(gè)月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓侵俗,卻偏偏與公主長得像,于是被迫代替她去往敵國和親丰刊。 傳聞我的和親對象是個(gè)殘疾皇子坡慌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評論 2 355

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

  • 創(chuàng)建和啟動線程 一個(gè)NSThread對象就代表一條線程 創(chuàng)建、啟動線程 NSThread *thread = [[...
    JonesCxy閱讀 217評論 0 0
  • 一藻三、創(chuàng)建和啟動線程 一個(gè) NSThread 對象代表一條線程。 創(chuàng)建和啟動線程 主線程相關(guān)用法 獲得當(dāng)前線程 線程...
    hrscy閱讀 353評論 2 3
  • 單例模式例子: https://github.com/XiaoRuiZuo/Singleton 多線程:多線程是為...
    Lee堅(jiān)武閱讀 1,403評論 0 50
  • 【專題:玉】 一逗概、玉不是奢侈物 玉,不是奢侈物忘衍。 提起奢侈品逾苫,便是富貴金銀,這大概我們心中第一個(gè)想到的吧枚钓。 玉铅搓,是...
    南陽雅月閱讀 1,349評論 0 0
  • 買了自己的第一盒煙,就在今天搀捷。 發(fā)現(xiàn)自己其實(shí)并不會吸煙星掰,直到今晚。當(dāng)真正把口腔中的煙吸入咽喉嫩舟,再緩緩將其咽下氢烘,...
    不得了3閱讀 245評論 0 1