創(chuàng)建和啟動線程
- 一個NSThread對象就代表一條線程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"jack"];
[thread start];
//線程一啟動足淆,就會在線程thread中執(zhí)行self的run方法
- 主線程相關方法
+ (NSThread *)mainThread//獲得主線程
+ (BOOL)isMainThread//是否為主線程
- (BOOL)isMainThread//是否為主線程
- 其他方法
- 獲得當前線程
NSThread *current = [NSThread currentThread];
- 線程的名字
- (void)setName:(NSString *)name;
- (NSString *)name;
其他創(chuàng)建線程方式
- 創(chuàng)建線程后自動啟動線程
[NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"rose"];
- 隱式創(chuàng)建并啟動線程
[self performSelectorInBackground:@selector(run:) withObject:@"jack"];
- 上述兩種創(chuàng)建線程方式的優(yōu)缺點
p 優(yōu)點:簡單快捷
p 缺點:無法對線程進行更詳細的設置
線程的狀態(tài)
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"jack"];
屏幕快照 2016-06-12 下午2.36.59.png
控制線程的狀態(tài)
- (void)start;
//進入就緒狀態(tài) -> 運行狀態(tài)。當線程任務執(zhí)行完畢,自動進入死亡狀態(tài)
- 阻塞(暫停線程)
+ (void)sleepUntilDate:(NSDate *)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
//進入阻塞狀態(tài)
//注意:一旦線程停止(死亡)了巧号,就不能再次開啟任務
多線程的安全隱患
資源共享
p 一塊資源可能會被多個線程共享族奢,也就是多個線程可能會訪問同一塊資源。
p 比如多個線程訪問同一個對象丹鸿、同一個變量越走、同一個文件當多個線程訪問同一塊資源時,很容易引發(fā)數(shù)據(jù)錯亂和數(shù)據(jù)安全問題靠欢。
安全隱患示例01 - 存錢取錢
屏幕快照 2016-06-12 下午2.50.00.png
- 安全隱患示例02 - 賣票
屏幕快照 2016-06-12 下午2.51.35.png
- 安全隱患分析
屏幕快照 2016-06-12 下午2.52.52.png
安全隱患解決 - 互斥鎖
屏幕快照 2016-06-12 下午2.54.26.png
- 互斥鎖使用格式
@synchronized(鎖對象){//需要鎖定的代碼}
//注意鎖定一份代碼只用1把鎖廊敌,用多把鎖是無效的
互斥鎖的優(yōu)缺點
1 優(yōu)點:能有效防止因多線程搶奪資源造成的數(shù)據(jù)安全問題
2 缺點:需要消耗大量的CPU資源互斥鎖的使用前提:多條線程搶奪同一塊資源
相關專業(yè)術語:線程同步
p 線程同步的意思是:多條線程在同一條線上執(zhí)行(按順序的執(zhí)行任務)
p 互斥鎖,就是使用了線程同步技術掺涛。
-互斥鎖代碼示例:
#import "ViewController.h"
@interface ViewController ()
/** 售票員01 */
@property (nonatomic, strong) NSThread *thread01;
/** 售票員02 */
@property (nonatomic, strong) NSThread *thread02;
/** 售票員03 */
@property (nonatomic, strong) NSThread *thread03;
/** 票的總數(shù) */
@property (nonatomic, assign) NSInteger ticketCount;
/** 鎖對象 */
//@property (nonatomic, strong) NSObject *locker;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// self.locker = [[NSObject alloc] init];
self.ticketCount = 100;
self.thread01 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
self.thread01.name = @"售票員01";
self.thread02 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
self.thread02.name = @"售票員02";
self.thread03 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
self.thread03.name = @"售票員03";
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.thread01 start];
[self.thread02 start];
[self.thread03 start];
}
- (void)saleTicket
{
while (1) {
@synchronized(self) {
// 先取出總數(shù)
NSInteger count = self.ticketCount;
if (count > 0) {
self.ticketCount = count - 1;
NSLog(@"%@賣了一張票庭敦,還剩下%zd張", [NSThread currentThread].name, self.ticketCount);
} else {
NSLog(@"票已經(jīng)賣完了");
break;
}
}
}
}
@end
原子和非原子屬性的選擇
nonatomic和atomic對比
p atomic :線程安全,需要消耗大量的資源
p nonatomic :非線程安全薪缆,是和內存小的移動設備iOS開發(fā)的建議
1.所有屬性都聲明為nonatomic
2.盡量避免多線程搶奪同一塊資源
3.盡量將加鎖秧廉、資源搶奪的業(yè)務邏輯交給服務器端處理,減小移動客戶端的壓力拣帽。
線程間通信
什么叫做線程間通信
p 在一個進程中疼电,線程往往不是孤立存在的,多個線程之間需要經(jīng)常通信减拭。線程間通信的提現(xiàn)
p 一個線程傳遞數(shù)據(jù)給另一個線程
p 在一個線程中執(zhí)行完特定任務后蔽豺,轉到另一個線程繼續(xù)執(zhí)行任務線程間通信常用方法
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait