iOS-多线程之NSThread

在iOS开发中,为了合理利用CPU的多核,提高程序的执行效率 和 用户体验,我们需要使用多线程。

iOS中常用的多线程技术有:NSThread,GCD,NSOperation

1 NSThread:OC语言,面向对象,简单易用,可直接操作线程对象;
2 GCD:C语言,旨在替代NSThread,充分利用了CPU的多核,不需要考虑线程的生命周期;
3 NSOperation:OC语言,面向对象,基于GCD(底层是GCD),比GCD更加简单实用,也不需要考虑线程的生命周期。

首先研究下 NSThread

    // 创建线程 01(通过创建线程对象创建线程) 
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(eat:) object:@"apple"];
    // 为线程明名
    thread.name = @"eat-thread";
    // 启动线程
    [thread start];

    注:一个NSThread对象就代表一条线程
    // 创建线程 02(隐式创建并启动线程)
[self performSelectorInBackground:@selector(eat:) withObject:@"apple"];
    // 创建线程 03 (类方法创建线程)
[NSThread detachNewThreadSelector:@selector(eat:) toTarget:self withObject:@"apple"];
- (void)eat:(NSString *)food {
     NSLog(@"eat---%@---%@", food, [NSThread currentThread]);
}
// 让线程睡眠n秒(阻塞n秒)
[NSThread sleepForTimeInterval:n]; 
// 让线程睡眠到某一时刻,苏醒后继续执行
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:3]];
// 直接退出线程
[NSThread exit]; 

线程之间的通信

1、什么叫做线程间通信?

在一个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信

2、线程间通信的体现

01: 一个线程传递数据给另一个线程
02 : 在一个线程中执行完特定任务后,转到另一个线程继续执行任务

线程间通信常用方法
// option 1
    - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
// option 2
    - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;

线程通信事例(利用子线程下载图片,回到主线程显示图片)

    // 创建一个子线程,用来下载图片 
    [self performSelectorInBackground:@selector(downloadImage) withObject:nil];

    // downloadImage function
    - (void)downloadImage {
    // 图片的网络路径
    NSURL *url = [NSURL URLWithString:@"http://xxx.jpg"];
    // 加载图片,并转为二进制文件(此方法耗内存和时间)
    NSData *data = [NSData dataWithContentsOfURL:url];
    // 生成图片
    UIImage *image = [UIImage imageWithData:data];

    // 回到主线程,显示图片 (与UI有关的操作,请放主线程)
    // option-1
    [self.imageView performSelector:@selector(setImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:NO];
    // option-2
    [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];
    // option-3
    [self performSelectorOnMainThread:@selector(showImage:) withObject:image waitUntilDone:YES];

}
// 设置图片的方法
-(void)showImage:(UIImage *)image {
      self.imageView.image = image;
}

主线程相关用法

    + (NSThread *)mainThread; // 获得主线程
    - (BOOL)isMainThread;     // 是否为主线程
    + (BOOL)isMainThread;     // 是否为主线程

线程安全 — 资源抢夺

一块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源
“比如多个线程访问同一个对象、同一个变量、同一个文件”
当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题

解决方案:使用互斥锁

互斥锁的使用前提:多条线程抢夺同一块资源

互斥锁使用格式
    @synchronized(锁对象) { 
    // 需要锁定的代码 
    }

优点:能有效防止因多线程抢夺资源造成的数据安全问题

缺点:需要消耗大量的CPU资源

你可能感兴趣的:(多线程,ios,面向对象,NSThread)