NSThread01

时间:2015-07-06 17:30:25   收藏:0   阅读:109

实例  01:

 

#import "ViewController.h"

@interface ViewController ()

@property(nonatomic,strong) UIImageView *imageViews;

@property (nonatomic, strong) NSURL *url;

@end

@implementation ViewController

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    // 创建一个线程对象 并且指定线程中要执行的方法

    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(downloadImage) object:nil];

    // 告诉CPU 线程准备就绪 可以随时准备接受调度

    [thread start];

}

/**

 *  耗时操作

 */

- (void)downloadImage{

    // 子线程下载图片

    NSData *data  = [NSData dataWithContentsOfURL:self.url];

    UIImage *image = [UIImage imageWithData:data];

    dispatch_async(dispatch_get_main_queue(), ^{

        // 主线程更新UI

        self.imageViews.image = image;

    });

}

 

- (UIImageView *)imageViews{

    if (_imageViews == nil) {

        _imageViews = [[UIImageView alloc] initWithFrame:self.view.bounds];

        [self.view addSubview:_imageViews];

    }

    return _imageViews;

}

- (NSURL *)url{

    if (_url == nil) {

        NSString *str = @"http://127.0.0.1/new/images/flower.jpg";

        _url = [NSURL URLWithString:str];

    }

    return _url;

}

@end

 

 

 

实例 02 : - -  NSThread 基本属性设置,

 

#import "ViewController.h"

@interface ViewController ()

@property(nonatomic,strong) UIImageView *imageViews;

@property (nonatomic, strong) NSURL *url;

@end

@implementation ViewController

 

 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    

    NSString *string = @"hellosam";

    // 创建线程

    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(testLongTimeOperation:) object:string];

    

    // 设置线程的名字

    thread.name = @"First";

    

    // 设置线程的优先级 0 ~ 1  ; 禁止设置优先级, 不然很容易造成优先级翻转

    //    thread.threadPriority = 0.5;

    

    // 设置线程调大小

    thread.stackSize = 1024*1024;

    

    // 获得当前线程

    [NSThread currentThread];

    

    // "开启"线程 告诉CPU线程准备就绪,

    [thread start];

    

    // 睡一会/ 阻塞 线程.

    // 没有任何区别

    [NSThread sleepForTimeInterval:3];

    

    NSDate *date = [NSDate dateWithTimeIntervalSinceNow:3];

    

    

    [NSThread sleepUntilDate:date];

    // 强制退出线程

    [NSThread exit];

    

    

    

}

*** 其他方法.

- (void)cancel NS_AVAILABLE(10_5, 2_0);

 

- (void)start NS_AVAILABLE(10_5, 2_0);

 

- (void)main NS_AVAILABLE(10_5, 2_0); // thread body method

 

 

- (void)testLongTimeOperation:(NSString *)str {

    

    NSData *data = [NSData dataWithContentsOfURL:self.url];

    UIImage *image = [UIImage imageWithData:data];

    // 回到主线程更新UI

    [self performSelector:@selector(testUpdateUI:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES];

    NSLog(@"%@ -- str = %@",[NSThread currentThread].name,str);

}

 

- (void)testUpdateUI:(UIImage *)image {

    

    self.imageViews.image = image;

    

}

 

- (UIImageView *)imageViews{

    if (_imageViews == nil) {

        _imageViews = [[UIImageView alloc] initWithFrame:self.view.bounds];

        [self.view addSubview:_imageViews];

    }

    return _imageViews;

}

- (NSURL *)url{

    if (_url == nil) {

        NSString *str = @"http://127.0.0.1/new/images/flower.jpg";

        _url = [NSURL URLWithString:str];

    }

    return _url;

}

 

 

console:

2015-07-06 12:05:53.057 多线程总结[1629:307100] First -- str = hellosam

 

 

 

实例 03: 从当前线程中分离出来的线程

 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    

    // 从当前线程中分离出一条新线程,不需要手动启动,会自动执行

    // 匿名对象,无法获得并设置其属性

    [NSThread detachNewThreadSelector:@selector(testDetachThread:) toTarget:self withObject:@"我是分离出来的线程"];

    

    

}

- (void)testDetachThread:(NSString *)str {

    

    NSLog(@"%@ -- %@",[NSThread currentThread],str);

    

    

}

 

 

console:

2015-07-06 12:13:30.584 多线程总结[1693:327945] <NSThread: 0x7fe988634860>{number = 2, name = (null)} -- 我是分离出来的线程

 

 

 

实例 04: 隐式创建线程

 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    

    // 隐式创建线程,生成匿名对象 自动执行

    [self performSelectorInBackground:@selector(testBackBroundThread:) withObject:@"我是隐式创建的线程对象"];

    

}

 

- (void)testBackBroundThread:(id)objc {

    

    NSData *data = [NSData dataWithContentsOfURL:self.url];

    

    UIImage *image = [UIImage imageWithData:data];

    

    // 回到主线程中更新UI

    dispatch_async(dispatch_get_main_queue(), ^{

        self.imageViews.image = image;

    });

    

    NSLog(@"%@ ---- %@",[NSThread currentThread],objc);

}

 

 

2015-07-06 12:21:39.165 多线程总结[1739:342398] <NSThread: 0x7fdeb9d20ec0>{number = 2, name = (null)} ---- 我是隐式创建的线程对象

 

 

 

 

* 线程间的通信:

 

1 > 子线程下载图片(耗时操作) 主线程(UI线程)更新UI

 

2 > 子线程执行耗时操作代码耗时操作,主线程执行更新UI操作代码

 

3 > 主线程中执行耗时操作代码,会影响UI线程的流畅度,产生卡顿现象

 

 

* 线程的状态:

 

start - - - - > 就绪 — —  运行 — —  退出 — 死亡

 

run — — start  —  — run

 

run  —  — sleep — — start

 

一旦线程执行exit 就会进入死亡状态,就不会再次开启

 

 

* 线程安全 :

 

当多条线程访问同一块资源的时候会产生数据安全的隐患

 

使用线程同步技术可以很有效的解决因多线程抢夺资源引发的数据安全问题

 

当然缺点也很明显: 消耗了大量的系统资源

 

 

1 > 解决方法:

互斥锁:

@synchronized(self/*锁对象*/){ /* 要加锁的资源(代码)  */ }

 

2 >  技巧:

[[NSUserDefaults standardUserDefaults] synchronize];

 

 

实例代码:

(经典问题,消费者和生产者)

 

错误实例:

 

@interface ViewController ()

@property(nonatomic,strong) NSThread *thread1;

@property(nonatomic,strong) NSThread *thread2;

@property(nonatomic,strong) NSThread *thread3;

/**

 *  产品剩余数量

 */

@property (nonatomic, assign) NSInteger ticketCount;

@end

 

@implementation ViewController

int cou = 0;

 

- (void)viewDidLoad{

    [super viewDidLoad];

    self.ticketCount = 100;

    self.thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(sell:) object:@"one"];

    self.thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(sell:) object:@"two"];

    self.thread3 = [[NSThread alloc] initWithTarget:self selector:@selector(sell:) object:@"three"];

}

- (void)sell:(NSString *)name{

    while (self.ticketCount) {

        if (self.ticketCount >0) {

            NSLog(@"%@ -- 剩余数量%ld------- %d",name,self.ticketCount,++cou);

        }

        self.ticketCount--;

        

    }

    

}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    [self.thread1 start];

    [self.thread2 start];

    [self.thread3 start];

}

 

 

 

解决方法:

 

解决方案(比较旧)

 

- (void)sell:(NSString *)name{

    while (self.ticketCount) {

        

        @synchronized(self){

            

            if (self.ticketCount >0) {

                NSLog(@"%@ -- 剩余数量%ld------- %d",name,self.ticketCount,++cou);

            }

            self.ticketCount--;

            

        }

        

    }

    

}

原理: 将并行执行方式改为串行执行,

 

 

 

 

pthread 的简单介绍

pthread是C语言使用多线程的方式

 

- (void)viewDidLoad{

    [super viewDidLoad];

    

    pthread_t myThread ;

    

    /**

     *  C语言使用多线程的方式

     *

     *  @param restrict#> 线程标识符的地址 (&myThread) description#>

     *  @param restrict#> 设置线程的一些属性 description#>

     *  @param 线程中执行的函数

     *  @param 传给线程中执行函数的参数

     *

     *  @return 返回值是0 表示创建成功 ,创建失败,返回别的状态码

     */

    NSString *string = @"hellosam";

    

    int result = pthread_create(&myThread, NULL, longTimeOp, (__bridge void *)(string));

    NSLog(@"%d",result);

    // void * 相当于OC中的id类型

    // __bridge 桥接,将OC数据类型传递给C语言函数

    // 添加桥接的目的是ARC下 OC和C混合开发 C语言不能自动管理内存,OC编译时特性会给OC自动添加内存管理代码,C语言没有这个功能,

    // 添加 (__bridge void *) 的目的就是告诉编译器,为OC自动添加内存管理操作;

    

}

/**

 *  该函数的返回值类型是void* 类型

 */

void *longTimeOp(void *data){

    NSString *str = (__bridge NSString *)(data);

    NSLog(@"%@",str);

    return NULL;

}

 

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!