一、NSThread 多線程的優缺點:
- 優點:NSThread比NSOperation和GCD輕量級;
- 缺點:需要自己管理線程的生命周期,線程同步。線程同步對資料的加鎖會有一定的系統開銷。
二、NSThread的使用:
1、NSThread有兩種直接建立方式:
- ①、- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument ;
- ②、+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;
例如:
// 這種建立線程⾃自動就運⾏行
(1)、動态建立
NSThread *t2 = [[NSThread alloc] initWithTarget:self selector:@selector(threadMain2:) object:nil];
// 設定線程的優先級(0.0 - 1.0,1.0最進階)
t2.threadPriority = 1;
[t2 start];
(2)、靜态建立
[NSThread detachNewThreadSelector:@selector(threadMain0:) toTarget:self withObject:@"111"];
- (void)threadMain0:(NSString *)obj{
NSLog(@"obj = %@",obj); //111
}
2、參數的意思
- ①、selector:線程執行的方法,這個selector隻能有一個參數,而且不能有傳回值;
- ②、target:selector消息發送對象;
- ③、object:傳輸給target的唯一參數,也可以為nil。
第一種方式會直接建立線程并且開始運作線程,第二種方式是先建立線程對象,然後再運作線程操作,在運作線程操作前可以設定線程的優先級等線程資訊。
3、隐藏式建立
[self performSelectorInBackground:@selector(threadMain3:) withObject:@"333”];
三、NSThread的屬性
NSThread* current = [NSThread currentThread];
1、傳回目前線程
+ (NSThread *)currentThread;
2、判斷是否為多線程
+ (BOOL)isMultiThreaded;
3、暫停
+ (void)sleepUntilDate:(NSDate *)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
4、退出線程
+ (void)exit;
5、設定線程的優先級(0.0,-1.0,1.0最高)
+ (double)threadPriority;
+ (BOOL)setThreadPriority:(double)p;
6、線程函數位址
+ (NSArray *)callStackReturnAddresses;
7、設定與傳回線程名稱 設定與傳回線程名稱
@property (copy) NSString *name;
8、線程堆棧
@property NSUInteger stackSize;
9、 判斷目前線程是否為主線程
+ (BOOL)isMainThread NS_AVAILABLE(10_5, 2_0);
+ (NSThread *)mainThread NS_AVAILABLE(10_5, 2_0);
10、是否在執行
@property (readonly, getter=isExecuting) BOOL executing;
11、是否已經結束
@property (readonly, getter=isFinished) BOOL finished;
12、是否取消的
@property (readonly, getter=isCancelled) BOOL cancelled;
13、取消操作
- (void)cancel NS_AVAILABLE(10_5, 2_0);
14、線程啟動
- (void)start NS_AVAILABLE(10_5, 2_0);
四、擷取目前線程
NSThread* current = [NSThread currentThread];
五、擷取主線程
NSThread* current = [NSThread mainThread];
六、暫停目前線程
1、暫停
[NSThread sleepForTimeInterval:2];
2、暫停
NSDate *date = [NSDate dateWithTimeInterval:2 sinceDate:[NSDate date]];
[NSThread sleepUntilDate:date]
七、線程間的通信
注意:線程入口函數一旦調用完成後該線程就結束了。
1、在指定線程上執行操作
[self performSelector:@selector(run) onThread:_myThread withObject:nil waitUntilDone:YES];
2、在主線程執行操作
[self performSelectorOnMainThread:@selector(run) withObject:nil waitUntilDone:YES];
3、在目前線程執行操作
[self performSelector:@selector(run) withObject:nil];
八、線程同步
1、NSLock
加鎖:
- ①、- (BOOL)tryLock;
- ②、- (void)lock;
- ③、- (BOOL)lockBeforeDate:(NSDate *)limit;
解鎖:
- ①、- (void)unlock;
2、synchornized代替NSLock
@synchronized(self)
{
// Everything between the braces is protected by the @synchronized directive.
}
@synchronized,代表這個方法加鎖, 相當于不管哪一個線程(例如線程A),運作到這個方法時,都要檢查有沒有其它線程例如B正在用這個方法,有的話要等正在使用synchronized方法的線程B運作完這個方法後再運作此線程A,沒有的話,直接運作。它包括兩種用法:synchronized 方法和 synchronized 塊。
@synchronized 方法控制對類(一般在IOS中用在單例中)的通路:每個類執行個體對應一把鎖,每個 synchronized 方法都必須獲得調用該方法鎖方能執行,否則所屬就會發生線程阻塞,方法一旦執行,就獨占該鎖,直到從該方法傳回時才将鎖釋放,此後被阻塞的線程方能獲得該鎖,重新進入可執行狀态。這種機制確定了同一時刻對于每一個類,至多隻有一個處于可執行狀态,進而有效避免了類成員變量的通路沖突(隻要所有可能通路類的方法均被聲明為 synchronized)。
synchronized 塊:
@通過 synchronized關鍵字來聲明synchronized 塊。文法如下:
@synchronized(syncObject) { }
synchronized 塊是這樣一個代碼塊,其中的代碼必須獲得對象 syncObject (如前所述,可以是類執行個體或類)的鎖方能執行,具體機制同前所述。由于可以針對任意代碼塊,且可任意指定上鎖的對象,故靈活性較高。
3、NSCondition
NSCodition是一種特殊類型的鎖,我們可以用它來同步操作執行的順序。等待某個NSCondition的線程一直被lock,知道其他線程給那個condition發送了信号。
例如:
- (void)run{
while (TRUE) {
// 上鎖
[ticketsCondition lock];
[ticketsCondition wait];
//操作
[ticketsCondition unlock];
}
}
//其他線程發送信号通知上面的線程,就可以運作了
-(void)run2{
while (YES) {
[ticketsCondition lock];
[NSThread sleepForTimeInterval:3];
[ticketsCondition signal];
[ticketsCondition unlock];
}
}