NSThread每個NSThread對象對應一個線程,輕量級。
NSThread:優點:NSThread比其他倆個輕量級,使用簡單。
缺點:需要自己管理線程的生命周期、線程同步、加鎖、睡眠以及喚醒等。線程同步對數據的加鎖會有一定的系統開銷。
NSThread的幾種創建方式
1 //方式一:利用perform開啟多線程,並且執行方法threadAction 2 // [self performSelectorInBackground:@selector(threadAction) withObject:@"thread"]; 3 4 //方式二: 5 // NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadAction:) object:@"text"]; 6 // thread.name = @"thread1"; 7 // //開啟線程 8 // [thread start]; 9 10 //方式三:開啟新的線程,並且執行 11 [NSThread detachNewThreadSelector:@selector(threadAction:) toTarget:self withObject:@"thread2"];
對比主線程與多線程在執行上的先后順序:
在viewDidLoad里寫一個for循環。
1 for (int i=0; i<50; i++) { 2 NSLog(@"主線程:%d",i); 3 }
在多線程的threadAction:方法里也同樣寫一個for循環
1 for (int i=0; i<50; i++) { 2 NSLog(@"多線程:%d",i); 3 }
打印結果:
通過倆次打印結果,我們知道他們是沒有先后順序的,而且每次打印都不同。
有幾個常用的方法我們可能會用到:
1 //獲取當前線程 2 NSThread *thread = [NSThread currentThread]; 3 //判斷當前是否在多線程 4 [NSThread isMultiThreaded] 5 //判斷當前是否在主線程 6 [NSThread isMainThread] 7 //讓當前線程睡眠幾秒 8 [NSThread sleepForTimeInterval:3]; 9 //回到主線程 10 // [self performSelectorOnMainThread:<#(SEL)#> withObject:<#(id)#> waitUntilDone:<#(BOOL)#>]
思考:我們為什么要使用多線程?
總結: 提高CPU的利用率,讓程序更加流暢。如果我們把所有的任務都放在主線程會造成主線程阻塞。比如說當你在加載較多的圖片時,你的textView是不能滾動的。下面我們就針對這方面寫一個demo.
首先我們給UIimageView添加一個類目,用來讓其能夠加載網絡圖片
類目的.h文件
1 #import <UIKit/UIKit.h> 2 3 @interface UIImageView (cache) 4 //為UIImageView寫一個添加網絡圖片的方法 5 - (void)setimage:(NSString *)str; 6 7 @end
類目的.m文件 #import "UIImageView+cache.h" @implementation UIImageView (cache) //如果這樣直接寫方法,在主線程,當我們在加載網絡時不能滑動TextView - (void)setimage:(NSString *)str { NSURL *url = [NSURL URLWithString:str]; NSData *data = [NSData dataWithContentsOfURL:url]; self.image = [UIImage imageWithData:data]; } @end
類目寫好了,讓我們用起來吧。 viewController里的代碼如下: #import "ViewController.h" #import "UIImageView+cache.h" @interface ViewController () { UIImageView *_image; NSMutableArray *arr; } - (IBAction)click:(UIButton *)sender; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; arr = [NSMutableArray array]; //創建八行六列的UIImageView for (int i = 0; i < 6; i ++) { for (int j = 0 ; j < 8; j ++) { _image = [[UIImageView alloc]initWithFrame:CGRectMake(i * 62, j * 62 , 60, 60)]; _image.backgroundColor = [UIColor yellowColor]; [self.view addSubview:_image]; //將創建好的UIImageView放進可變數組。 [arr addObject:_image]; } } } - (IBAction)click:(UIButton *)sender { for (UIImageView *imageview in arr) { //利用分類給數組里的UIImageView添加圖片 [imageview setimage:@"http://img31.mtime.cn/pi/2013/03/08/144644.81111130_1280X720.jpg"]; } } @end
這樣的運行結果是:
那么為了解決這樣阻塞主線程的情況 我們把分類的方法該為: - (void)setimage:(NSString *)str { //開啟一個多線程,並且把str通過創建多線程傳遞到多線程的任務中(注:這里的字符串為網絡圖片的地址) [NSThread detachNewThreadSelector:@selector(thredAction:) toTarget:self withObject:str]; } //多線程的任務 - (void)thredAction:(NSString *)str { //將字符串轉換成URL NSURL *url = [NSURL URLWithString:str]; //將url轉化成data NSData *data = [NSData dataWithContentsOfURL:url]; //注意:UI的修改只能放在主線程 所以寫在這里還是錯誤 //self.image = [UIImage imageWithData:data]; //回到主線程 [self performSelectorOnMainThread:@selector(setImage:) withObject:[UIImage imageWithData:data] waitUntilDone:YES]; } 這樣就可以解決線程阻塞的問題了。