多线程 - 课程分析
来源:互联网 发布:淘宝网售后服务网址 编辑:程序博客网 时间:2024/05/18 00:20
http://blog.csdn.net/fuzheng0301/article/details/46685917
1.每个进程至少包含一个线程,这个默认创建的线程被成为主线程
2.单线程程序:程序只包含一个线程(主线程),线程中的代码按顺序执行,缺点:可能会造成主线程阻塞(有些任务耗时比较长)
3.多线程程序:程序中包含多个线程,线程是独立运行的,提高程序运行效率.
4.iOS开发中,所有跟UI有关的操作(绘制,刷新)都必须在主线程中完成.
5.子线程:主线程之外创建的新的线程
△.线程是可以设置优先级的
获取当前线程,判断是否是主线程的方法:
- NSLog(@"当前线程 %@ ------ 是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
先创建一个多线程测试环境:
- -(void)cycle
- {
- //获取当前线程,判断是否是主线程
- NSLog(@"当前线程 %@ ------ 是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- int sum = 0;
- for (int i=0; i<500; i++) {
- sum += i;
- // NSLog(@"%d",i);
- }
- // NSLog(@"%d",sum);
- }
一 . 使用NSThread实现多线程 : 创建线程后,自动开启,无需手动调用开启
1.第一个参数:线程中需要执行的方法
2.第二个参数:执行方法的对象
3.第三个参数:传值
- [NSThread detachNewThreadSelector:@selector(cycle) toTarget:self withObject:nil];
二 . 使用NSThread实现多线程 : 创建线程后,需要手动开启
- NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(cycle) object:nil];
- [thread start];
三 . 使用NSObject类目方法实现多线程(用的比较多)
- //隐式创建线程
- [self performSelectorInBackground:@selector(cycle) withObject:nil];
- //图片网址
- NSString * url = @"http://a.hiphotos.baidu.com/image/pic/item/96dda144ad3459824a56a41a0ef431adcaef845e.jpg";
- [self performSelectorInBackground:@selector(downloadImage:) withObject:url];
- //在子线程中,同步连接下载图片
- -(void)downloadImage:(NSString *)url
- {
- //在子线程中,使用同步方式下载图片. △备注:在子线程中,不要使用异步连接,会出现问题
- /*
- △注意事项:
- 1.子线程中没有自动释放池,需要手动添加
- 2.NSThread创建的子线程,默认情况下,任务执行完成后,线程被关闭,销毁
- 3.在子线程中,NSTimer默认情况下,不会执行.如果在子线程中使用NSTimer,必须开启runLoop,方法如下:
- 4.所有线程都有runLoop,主线程默认是开启状态,子线程默认是关闭状态
- 5.子线程开启runLoop后,runLoop不停止,线程无法关闭
- */
- //获取当前线程的runLoop,并开启
- // [[NSRunLoop currentRunLoop] run];
- //获取当前线程的runLoop,并设定运行的时间
- // [[NSRunLoop currentRunLoop] runUntilDate:<#(NSDate *)#>];
- //获取当前线程,判断是否是主线程
- NSLog(@"当前线程 %@ ------ 是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- //同步下载图片
- NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
- //将data转换成image对象
- UIImage *image = [UIImage imageWithData:data];
- //△注意:将image在主线程中进行显示.
- // _imageView.image = image;//这句话位置不对,不能写在这里
- [self performSelectorOnMainThread:@selector(showImage:) withObject:image waitUntilDone:YES];//第三个参数:等待子线程任务执行完成,再回到主线程执行
- //直接给imageView附图片
- // [_imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];
- }
- //在主线程中,将image显示在imageView上
- -(void)showImage:(UIImage *)image
- {
- //获取当前线程,判断是否是主线程
- NSLog(@"当前线程 %@ ------ 是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- //参数image是从子线程中返回
- _imageView.image = image;
- }
四 . NSOperation 是一个操作类(抽象类),封装了需要执行的任务和数据. 一般不直接使用NSOperation,使用子类:NSInvocationOperation和NSBlockOperation
- //操作对象封装了需要执行的任务和参数
- NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(cycle) object:nil];
- //开始执行operation对象中封装的任务(方法)
- //start在哪个线程中调用,operation对象中封装的方法就在哪个线程中执行
- [operation start];
五 . block方法:
- NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
- NSLog(@"当前线程 %@ ----- 是否是主线程:%d", [NSThread currentThread], [NSThread isMainThread]);
- for (int i = 1; i < 500; i++) {
- }
- }];
- [operation start];
六 . NSOperationQueue :
1.NSOperationQueue 操作队列(先进先出),可以管理多个操作对象.
2.NSOperationQueue 创建的多线程是可以重复使用的,是非脱离线程(线程中的任务完成后,线程进入睡眠状态,未被销毁;NSThread创建的线程是脱离线程)
3.NSOperationQueue 先加入队列的任务,先执行.(即"先进先出")
4.NSOperationQueue 控制的线程是并发执行的. 即:队列中的任务按照加入队列的顺序进行分派,但是下一个任务不用等待前一个任务完成再开始.多个任务可以同时执行,互不干扰. ("并发"相对的是"串行")
5.什么叫线程同步? 线程A执行结束后才能执行线程B
6.NSOperationQueue如何实现线程同步? 把最大并发数设置为1,即:每次只允许一个线程执行任务
7.队列下载
- NSOperationQueue * queue = [[NSOperationQueue alloc]init];
- //设置最大并发数
- queue.maxConcurrentOperationCount = 1;
- //添加10个任务
- for (int i=0; i<10; i++) {
- NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(cycle) object:nil];
- //操作对象添加到队列里
- [queue addOperation:operation];
- }
七 . 使用GCD的队列实现串行(任务1执行后,任务2再执行) :
1.GCD队列类型:主队列,全局队列,自定义队列
2.GCD队列功能:串行,并发
3.能够实现串行的有两种队列:主队列和自定义串行队列
4.能够实现并发的有两种队列:全局队列和自定义并发队列
- //串行队列 第一种实现:使用主队列
- /*
- dispatch_queue_t queue = dispatch_get_main_queue();
- //向队列异步添加任务
- dispatch_async(queue, ^{
- NSLog(@"第一个任务,所在线程:%@,是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- });
- dispatch_async(queue, ^{
- NSLog(@"第二个任务,所在线程:%@,是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- });
- dispatch_async(queue, ^{
- NSLog(@"第三个任务,所在线程:%@,是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- });
- dispatch_async(queue, ^{
- NSLog(@"第四个任务,所在线程:%@,是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- });
- dispatch_async(queue, ^{
- NSLog(@"第五个任务,所在线程:%@,是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- });
- */
- //串行队列 第二种实现:使用自定义串行队列
- dispatch_queue_t queue = dispatch_queue_create("com.lanou3g.Thread.myQueue", DISPATCH_QUEUE_SERIAL);
- dispatch_async(queue, ^{
- NSLog(@"第一个任务,所在线程:%@,是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- });
- dispatch_async(queue, ^{
- NSLog(@"第二个任务,所在线程:%@,是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- });
- dispatch_async(queue, ^{
- NSLog(@"第三个任务,所在线程:%@,是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- });
- dispatch_async(queue, ^{
- NSLog(@"第四个任务,所在线程:%@,是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- });
- dispatch_async(queue, ^{
- NSLog(@"第五个任务,所在线程:%@,是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- });
- //释放(注意:MRC下需要释放)
- // dispatch_release(queue);
八 . GCD并发:任务A,B,C....按照进入队列顺序开始分派执行
- //并发队列 第一种实现:全局队列
- /*
- dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- dispatch_async(queue, ^{
- NSLog(@"第一个任务,所在线程:%@,是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- });
- dispatch_async(queue, ^{
- NSLog(@"第二个任务,所在线程:%@,是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- });
- dispatch_async(queue, ^{
- NSLog(@"第三个任务,所在线程:%@,是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- });
- dispatch_async(queue, ^{
- NSLog(@"第四个任务,所在线程:%@,是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- });
- dispatch_async(queue, ^{
- NSLog(@"第五个任务,所在线程:%@,是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- });
- */
- //并发队列 第二种实现:使用自定义并发队列
- dispatch_queue_t queue = dispatch_queue_create("com.lanou3g.Thread.myQueue", DISPATCH_QUEUE_CONCURRENT);
- dispatch_async(queue, ^{
- NSLog(@"第一个任务,所在线程:%@,是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- });
- dispatch_async(queue, ^{
- NSLog(@"第二个任务,所在线程:%@,是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- });
- dispatch_async(queue, ^{
- NSLog(@"第三个任务,所在线程:%@,是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- });
- dispatch_async(queue, ^{
- NSLog(@"第四个任务,所在线程:%@,是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- });
- dispatch_async(queue, ^{
- NSLog(@"第五个任务,所在线程:%@,是否是主线程:%d",[NSThread currentThread],[NSThread isMainThread]);
- });
九 . GCD
- //在子线程中建立同步连接下载图片(把任务添加到全局队列)
- dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- dispatch_async(queue, ^{
- //建立同步连接下载图片
- //图片网址
- NSString * url = @"http://a.hiphotos.baidu.com/image/pic/item/96dda144ad3459824a56a41a0ef431adcaef845e.jpg";
- NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
- UIImage *image = [UIImage imageWithData:data];
- NSLog(@"同步连接下载图片,当前线程:%@",[NSThread currentThread]);
- //在主线程中,显示下载的图像
- dispatch_async(dispatch_get_main_queue(), ^{
- _imageView.image = image;
- NSLog(@"显示下载图片,当前线程:%@",[NSThread currentThread]);
- });
- });
十 . 总结:
1.耗费时间的两种方式:下载(跟网速有关)和处理数据
2. 任务 线程 方法
触发下载图片 主线程 didClick....Button
建立同步连接下载图片 子线程 download
3.
/*
1.每个进程至少包含一个线程,这个默认创建的线程被成为主线程
2.单线程程序:程序只包含一个线程(主线程),线程中的代码按顺序执行,缺点:可能会造成主线程阻塞(有些任务耗时比较长)
3.多线程程序:程序中包含多个线程,线程是独立运行的,提高程序运行效率.
4.iOS开发中,所有跟UI有关的操作(绘制,刷新)都必须在主线程中完成.
5.子线程:主线程之外创建的新的线程
△.线程是可以设置优先级的
*/
4.
/*
△注意事项:
1.子线程中没有自动释放池,需要手动添加
2.NSThread创建的子线程,默认情况下,任务执行完成后,线程被关闭,销毁
3.在子线程中,NSTimer默认情况下,不会执行.如果在子线程中使用NSTimer,必须开启runLoop,方法如下:
4.所有线程都有runLoop,主线程默认是开启状态,子线程默认是关闭状态
5.子线程开启runLoop后,runLoop不停止,线程无法关闭
*/
//获取当前线程的runLoop,并开启
// [[NSRunLoop currentRunLoop] run];
//获取当前线程的runLoop,并设定运行的时间
// [[NSRunLoop currentRunLoop] runUntilDate:<#(NSDate *)#>];
5.
/*
1.NSOperationQueue 操作队列(先进先出),可以管理多个操作对象.
2.NSOperationQueue 创建的多线程是可以重复使用的,是非脱离线程(线程中的任务完成后,线程进入睡眠状态,未被销毁;NSThread创建的线程是脱离线程)
3.NSOperationQueue 先加入队列的任务,先执行.(即"先进先出")
4.NSOperationQueue 控制的线程是并发执行的. 即:队列中的任务按照加入队列的顺序进行分派,但是下一个任务不用等待前一个任务完成再开始.多个任务可以同时执行,互不干扰. ("并发"相对的是"串行")
5.什么叫线程同步? 线程A执行结束后才能执行线程B
6.NSOperationQueue如何实现线程同步? 把最大并发数设置为1,即:每次只允许一个线程执行任务
7.队列下载
*/
6.
△.注意:GCD不等于多线程
- 多线程 - 课程分析
- 多线程 - 课程分析
- 多线程基础课程
- UI课程22 多线程、GCD
- 多线程分析
- 电子商务案例分析模型---课程
- IBM 大型机培训课程分析
- 《Linux操作系统分析》课程笔记
- 泛函分析前导课程
- 课程简介及算法分析
- 《Linux内核分析》课程总结
- Linux内核分析MOOC课程汇编分析
- 《问卷分析与分析思维培养》课程
- 《问卷分析与分析思维培养》课程
- java 多线程课程 包括多线程的实现和生命周期
- 偶这学年的课程分析
- 《算法分析与设计》课程作业
- 互联网数据分析和挖掘公开课程
- 推荐ubuntu好用的词典stardict (安装及免费词库下载)
- Android应用程序:简单拨号器
- Linux select和poll系统调用
- 网盘秒传的实现方式
- NOIP2014提高组解方程
- 多线程 - 课程分析
- Manacher算法
- TCP/IP协议三次握手及断开
- mysql当中时间类型是如何存储的
- 28-正则表达式-01-正则表达式(概述)
- python 学习点滴
- mysql主从灾备
- Redis字符串的巧妙处理
- linux内核之系统初始化