1. 程式人生 > >NSThread那些事兒

NSThread那些事兒

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那些事兒