美文网首页ios多线程
iOS多线程实现——NSThread的简单使用

iOS多线程实现——NSThread的简单使用

作者: 听海听心 | 来源:发表于2017-08-30 15:14 被阅读35次

关于iOS多线程的实现方式有多种,今天来共同学习一下NSThread的简单使用,有疏忽的地方,还望各位不吝赐教。


一、NSThread初始化

// 1、创建线程 

/**
* 第一种方式创建线程
* 参数说明
* 第一个参数:目标对象 self
* 第二个参数:方法选择器 调用的方法
* 第三个参数:调用方法需要传递的参数 (进行赋值后可以在run:方法中当做参数接收)
*/

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(open:) object:@"创建线程"];

// 2、对线程可以进行命名。

thread.name = @"线程名称,以示区分";

// 3、线程优先级,范围是0.0-1.0 数字越大,被执行到的可能性越大,只是可能性不代表一定会被执行。

thread.threadPriority = 0.5;

// 4、开启线程

[thread start];

// 5、实现调用的方法

- (void)open:(NSString *)param{

//  [NSThread currentThread]  此方法可以获得当前线程

//  [NSThread mainThread]  此方法可以获得主线程

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

}

// 打印: 创建线程---------{number = 3, name = 线程名称,以示区分}

/**

* 第二种方式创建线程

* 参数说明

* 第一个参数:方法选择器 调用的方法

* 第二个参数:目标对象 self

* 第三个参数:调用方法需要传递的参数 (进行赋值后可以在run:方法中当做参数接收)

*/

// 1、此方法没有返回值 相当于创建并启动线程

[NSThread detachNewThreadSelector:@selector(open:) toTarget:self withObject:@"分离子线程"];

// 2、实现调用的方法

- (void)open:(NSString *)param{

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

}

// 打印:分离子线程---------{number = 3, name = (null)}

/**

* 第三种方式创建线程

* 参数说明

* 第一个参数:方法选择器 调用的方法

* 第二个参数:调用方法需要传递的参数 (进行赋值后可以在run:方法中当做参数接收)

*/

// 1、此方法没有返回值 隐式创建并启动线程

[self performSelectorInBackground:@selector(open:) withObject:@"开启后台线程"];

// 2、实现调用的方法

- (void)open:(NSString *)param{

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

}

// 打印:开启后台线程---------{number = 3, name = (null)}

二、暂停当前线程

/**

* 暂停当前线程(阻塞)方式一

* 此方法代表让当前线程休眠两秒后再进行其他操作

*/

[NSThread sleepForTimeInterval:2.0];

/**

* 暂停当前线程(阻塞)方式二

* 此方法代表让当前线程休眠两秒后再进行其他操作

*/

[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];

三、退出当前线程

/**

* 退出当前线程

* 此方法代表强制退出当前线程

*/

[NSThread exit];

四、线程之间的通信

/**

*  关于线程之间的通信的说明:

*  1、主线程是专门用来进行更新UI和处理用户事件的线程,一般耗时操作放在子线程中执行。

*  2、当子线程将任务完成后,需要和主线程进行通信,将获取的数据展示到UI中,以便和用户进行交互。 

*   在此使用一个例子来进行说明:在子线程中下载一张图片,然后在主线程中进行展示。

*/

// 1、使用第二种方式创建线程

  [NSThread detachNewThreadSelector:@selector(downloadImage) toTarget:self withObject:nil];

// 2、进行downloadImage方法的实现

- (void)downloadImage{

// 2.1、确定图片的URL地址

    NSURL *url = [NSURL URLWithString:@"此处需要图片的URL地址"];

// 2.2、根据图片的URL地址下载图片二进制数据到本地

    NSData *data = [NSData dataWithContentsOfURL:url];

// 2.3、转换图片格式 将二进制数据转换为图片数据

    UIImage *image = [UIImage imageWithData:data];

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

// 2.4、将图片数据交给主线程显示图片 以下三种方式任选一种即可

/**

* 与主线程通信的方式一

* 第一个参数:回到主线程调用哪个方法

* 第二个参数:前面方法要传递的参数

* 第三个参数:是否等待 如果等待相当于当前方法为阻塞状态,end的打印会在图片显示方法执行完后进行打印

*/

 [self performSelectorOnMainThread:@selector(showImage:) withObject:image waitUntilDone:NO];

/**

* 与主线程通信的方式二

* 第一个参数:回到主线程调用哪个方法

* 第二个参数:指定哪个线程执行showImage:的方法(本方法相比于方式一可以指定线程执行)

* 第三个参数:前面方法要传递的参数

* 第四个参数:是否等待 如果等待相当于当前方法为阻塞状态,end的打印会在图片显示方法执行完后进行打印

*/

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

NSLog(@"end-------------------------end");

}

// 3、显示图片的方法

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

   // 打印当前线程信息

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

   // 显示图片

   self.iconImageView.image = image;

}

/**

* 与主线程通信的方式三

* 说明:

* 1、使用此方法可以省略以上显示图片的方法,故而写在这里,此代码与以上建立与主线程通信代码书写的位置相同;

* 2、因为在此案例中是直接在UIImageView中进行图片赋值,所以本方法具有特殊性。

* 3、可以使用的原因是因为performSelector:onThread:方法是在NSObject的分类中,所以只要是对象就可以进行调用。

*/

[self.iconImageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];

五、线程的声明周期

当线程中的任务执行完毕后才会释放,并不会因为它是一个局部变量,在出了作用域后就被释放。

关于线程的状态的声明:

1、New(创建)

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(open:) object:@"创建线程"]; // 此代码执行完毕后会在内存中创建一个线程对象。

2、Runnable(就绪状态)

[thread start]; // 线程对象进入就绪状态,并放入可调度线程池中,只有在可调度线程池中的线程对象才可以被系统调度。

3、Running(运行状态)

当线程对象被系统调度时就处在运行状态,在系统调度其他线程的时候,就进入就绪状态。

4、Blocked(阻塞状态)

在调用sleep等方法的时候,线程会进入阻塞状态。线程对象会被从可调度线程池中移除出来,这个时候线程对象还在内存中存在,但是系统不会调度这个线程对象。

当然了,当sleep的设置时间到了以后,会再从内存中将线程对象放入可调度线程池中,线程对象会再进入就绪状态。

5、Dead(死亡状态)

当线程对象把任务执行完毕或者被强制退出,则进入死亡状态。这个时候内存中线程对象被销毁,内存中已经没有此线程对象了。

六、自定义NSThread

/**

* 说明

* 1、 关于自定义的NSThread创建线程的方式可以使用allac init 进行创建;

*  2、在自定义NSThread的.m文件中实现main方法,写在这里就可以实现自定义NSThread执行指定的任务;

* 3、当查看其它工程的源码,发现NSThread创建线程的方式是以下方式,则方便查找相关任务的执行代码。

*/

//  1、进行线程的创建

GHThread *thread = [[GHThread alloc] init];

//  2、开启线程

[thread start];

// 3、在GHThread.m中实现main方法

- (void)main{

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

}

// 打印:end---------{number = 5, name = (null)}


写在最后的话:关于NSThread虽然简单易用,可以直接操作线程对象,但是线程的生命周期需要手动管理,使用频率不是很高。关于iOS多线程的其他实现方式会在以后继续学习和分享。。。。。。

相关文章

网友评论

    本文标题:iOS多线程实现——NSThread的简单使用

    本文链接:https://www.haomeiwen.com/subject/habzdxtx.html