多線程NSThread的使用

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];
    
}
這樣就能夠解決線程阻塞的問題了。
相關文章
相關標籤/搜索