NSThread那些事兒
阿新 • • 發佈:2017-08-30
sage com strong prop block cti 線程優先級 初始化 tar
NSThread
哎呀,它面向對象,再去看看蘋果提供的API,對比一下Pthreads,簡單明了,人生仿佛又充滿了陽光和希望,我們先來一看一下系統提供給我們的API自然就知道怎麽用了,來來來,我給你註釋一下啊:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
@interface NSThread : NSObject //當前線程
@property (class, readonly, strong) NSThread *currentThread;
//使用類方法創建線程執行任務
+ (void)detachNewThreadWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;
//判斷當前是否為多線程 + (BOOL)isMultiThreaded;
//指定線程的線程參數,例如設置當前線程的斷言處理器。
@property (readonly, retain) NSMutableDictionary *threadDictionary;
//當前線程暫停到某個時間
+ (void)sleepUntilDate:(NSDate *)date;
//當前線程暫停一段時間
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
//退出當前線程
+ (void)exit;
//當前線程優先級
+ (double)threadPriority;
//設置當前線程優先級
+ (BOOL)setThreadPriority:(double)p; //指定線程對象優先級 0.0~1.0,默認值為0.5
@property double threadPriority NS_AVAILABLE(10_6, 4_0);
//服務質量
@property NSQualityOfService qualityOfService NS_AVAILABLE(10_10, 8_0);
//線程名稱
@property (nullable, copy) NSString *name NS_AVAILABLE(10_5, 2_0);
//棧區大小
@property NSUInteger stackSize NS_AVAILABLE(10_5, 2_0);
//是否為主線程
@property (class, readonly) BOOL isMainThread NS_AVAILABLE(10_5, 2_0);
//獲取主線程
@property (class, readonly, strong) NSThread *mainThread NS_AVAILABLE(10_5, 2_0);
//初始化
- (instancetype)init NS_AVAILABLE(10_5, 2_0) NS_DESIGNATED_INITIALIZER;
//實例方法初始化,需要再調用start方法
- (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument NS_AVAILABLE(10_5, 2_0);
- (instancetype)initWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
//線程狀態,正在執行
@property (readonly, getter=isExecuting) BOOL executing NS_AVAILABLE(10_5, 2_0);
//線程狀態,正在完成
@property (readonly, getter=isFinished) BOOL finished NS_AVAILABLE(10_5, 2_0);
//線程狀態,已經取消
@property (readonly, getter=isCancelled) BOOL cancelled NS_AVAILABLE(10_5, 2_0);
//取消,僅僅改變線程狀態,並不能像exist一樣真正的終止線程
- (void)cancel NS_AVAILABLE(10_5, 2_0);
//開始
- (void)start NS_AVAILABLE(10_5, 2_0);
//線程需要執行的代碼,一般寫子類的時候會用到
- (void)main NS_AVAILABLE(10_5, 2_0);
@end
另外,還有一個NSObject的分類,瞅一眼:
@interface NSObject (NSThreadPerformAdditions)
//隱式的創建並啟動線程,並在指定的線程(主線程或子線程)上執行方法。
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<nsstring *> *)array;
- (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 modes:(nullable NSArray<nsstring *> *)array NS_AVAILABLE(10_5, 2_0);
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0);
- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg NS_AVAILABLE(10_5, 2_0);
@end</nsstring *></nsstring *>
|
上面的介紹您還滿意嗎?小的幫您下載一張圖片,您瞧好:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
-(void)creatBigImageView{
self.bigImageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:_bigImageView];
UIButton *startButton = [UIButton buttonWithType:UIButtonTypeSystem];
startButton.frame = CGRectMake(0, 0, self.view.frame.size.width / 2, 50);
startButton.backgroundColor = [UIColor grayColor];
[startButton setTitle:@ "開始加載" forState:UIControlStateNormal];
[startButton addTarget:self action:@selector(loadImage) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:startButton];
UIButton *jamButton = [UIButton buttonWithType:UIButtonTypeSystem];
jamButton.frame = CGRectMake(self.view.frame.size.width / 2, 0, self.view.frame.size.width / 2, 50);
jamButton.backgroundColor = [UIColor grayColor];
[jamButton setTitle:@ "阻塞測試" forState:UIControlStateNormal];
[jamButton addTarget:self action:@selector(jamTest) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:jamButton];
}
-(void)jamTest{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@ "線程阻塞" message:@ "" delegate:nil cancelButtonTitle:@ "好" otherButtonTitles:nil, nil];
[alertView show];
}
-(void)loadImage{
NSURL *imageUrl = [NSURL URLWithString:@ "http://img5.duitang.com/uploads/item/201206/06/20120606174422_LZSeE.thumb.700_0.jpeg" ];
NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];
[self updateImageData:imageData];
}
-(void)updateImageData:(NSData*)imageData{
UIImage *image = [UIImage imageWithData:imageData];
self.bigImageView.image = image;
}
|
運行結果:
我們可以清楚的看到,主線程阻塞了,用戶不可以進行其他操作,你見過這樣的應用嗎?
所以我們這樣改一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
-(void)creatBigImageView{
self.bigImageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:_bigImageView];
UIButton *startButton = [UIButton buttonWithType:UIButtonTypeSystem];
startButton.frame = CGRectMake(0, 20, self.view.frame.size.width / 2, 50);
startButton.backgroundColor = [UIColor grayColor];
[startButton setTitle:@ "開始加載" forState:UIControlStateNormal];
[startButton addTarget:self action:@selector(loadImageWithMultiThread) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:startButton];
UIButton *jamButton = [UIButton buttonWithType:UIButtonTypeSystem];
jamButton.frame = CGRectMake(self.view.frame.size.width / 2, 20, self.view.frame.size.width / 2, 50);
jamButton.backgroundColor = [UIColor grayColor];
[jamButton setTitle:@ "阻塞測試" forState:UIControlStateNormal];
[jamButton addTarget:self action:@selector(jamTest) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:jamButton];
}
-(void)jamTest{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@ "阻塞測試" message:@ "" delegate:nil cancelButtonTitle:@ "好" otherButtonTitles:nil, nil];
[alertView show];
}
-(void)loadImageWithMultiThread{
//方法1:使用對象方法
//NSThread *thread=[[NSThread alloc]initWithTarget:self selector:@selector(loadImage) object:nil];
//??啟動一個線程並非就一定立即執行,而是處於就緒狀態,當CUP調度時才真正執行
//[thread start];
//方法2:使用類方法
[NSThread detachNewThreadSelector:@selector(loadImage) toTarget:self withObject:nil];
}
-(void)loadImage{
NSURL *imageUrl = [NSURL URLWithString:@ "http://img5.duitang.com/uploads/item/201206/06/20120606174422_LZSeE.thumb.700_0.jpeg" ];
NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];
//必須在主線程更新UI,Object:代表調用方法的參數,不過只能傳遞一個參數(如果有多個參數請使用對象進行封裝),waitUntilDone:是否線程任務完成執行
[self performSelectorOnMainThread:@selector(updateImageData:) withObject:imageData waitUntilDone:YES];
//[self updateImageData:imageData];
}
-(void)updateImageData:(NSData*)imageData{
UIImage *image = [UIImage imageWithData:imageData];
self.bigImageView.image = image;
}
|
運行結果:
哎呀,用多線程果然能解決線程阻塞的問題,並且NSThread也比Pthreads好用,仿佛你對精通熟練使用多線程又有了一絲絲曙光。假如我有很多不同類型的任務,每個任務之間還有聯系和依賴,你是不是又懵逼了,上面的你是不是覺得又白看了,其實開發中我覺得NSThread用到最多的就是[NSThread currentThread];了。(不要慌,往下看... ...)
轉自:http://www.cocoachina.com/ios/20170829/20404.html
NSThread那些事兒