iOS开发学习之多线程
来源:互联网 发布:shake it off下载 编辑:程序博客网 时间:2024/04/30 01:19
- 多线程
1进程指在系统运行的程序 如:QQ Xcode两个正在运行的进程
2每一个进程至少有一条线程,进程的所有的任务都在线程中执行,线程是进程的基本执行单元。
3线程的串行,一条线程只能执行一个任务,可以认为线程是进程中的执行路径
4原理:进程好比车间,线程好比车间工人。同一时间内,CPU只处理一条线程,多线程并发执行,其实是CPU快速地在多线程之间调度和切换。
5过度使用开启多个线程会造成不好的后果 1.CPU会累死 2.每条线程被调度执行的频率会降低 3.占用一定的内存空间 4.CPU调度线程的开销就越大
6实现方案:Pthread/NSThread/GCD/NSOperation
- 主线程
作用:1.显示UI界面 2.处理UI事件(点击,滚动,拖拉)
注意:不要将耗时的操作放到主线程中,不然会出现“卡”的不良用户体验。解决措施:将耗时操作放在子线程(非主线程/后台线程),这样用户点击就能做出反应,能同时处理耗时操作和UI控件事件。
- 多线程的多种创建方式
1.Pthread创建子线程 不过不常用。
/** * 1.pthread创建子线程 */-(void)pthread{ NSThread *currentThread = [NSThread currentThread]; NSLog(@"%@", currentThread); pthread_t threadId; pthread_create(&threadId, NULL, run, NULL);}void *run(void *data){ NSThread *currentTread = [NSThread currentThread]; NSLog(@" %@",currentTread); return NULL;}
2.NSThread可通过initWithTarget:Selector:Object创建一条子线程,并用start方法开启线程。
/** * 2.用NSThread创建子线程并start开启线程 */-(void)NSThread{ // 创建子线程 NSThread *currentThread1 = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"JHA"]; currentThread1.name = @"线程A"; // 开启线程 [currentThread1 start]; // 创建子线程 NSThread *currentThread2 = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"JHB"]; currentThread2.name = @"线程B"; // 开启线程 [currentThread2 start]; }
3.隐式创建子线程并启动
/** * 隐式创建子线程自动启动线程 (在后台进行) */-(void)performSelectorInBackground{ // 在后台执行 == 在子线程执行 [self performSelectorInBackground:@selector(run:) withObject:@"performSlectorInback"];}
4.创建线程后自动启动线程
/** * 4.断开分成两条新的线程 */-(void)detachNewThread{ [NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"detachNewThread.A"]; [NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"detachNewThread.B"];}-(void)run:(NSString *)param{ for (int i=0; i<100; i++) { NSThread *current = [NSThread currentThread]; NSLog(@" %@ --run -- %@",current,param); }}
第3种方式和第4种方式的缺点:无法对线程进行更详细的设置
- 多线程的安全隐患
解决措施:加锁
枷锁格式:@synchronized(锁对象){} 注意:只能是同一把锁
加锁前提:多条线程抢夺同一块资源
线程同步:表示多条线程按顺序地执行,其实本质就是在线程当中加锁
我们在开发项目的时候,一些特殊属性 它们也被加了锁。
atomic:原子属性.会为setter方法加锁
nonatomic:非原子属性,不会为setter方法加锁
atomic:线程安全 需要消耗大量的资源
nonatomic:非线程安全,适用内存小的移动设备
先下代码说明多线程抢夺资源后引发的安全性问题。
//// JHViewController.m// 线程安全//// Created by cjj on 15-10-28.// Copyright (c) 2015年 jh.chen. All rights reserved.//#import "JHViewController.h"@interface JHViewController ()@property (nonatomic, strong) NSThread *thread1;@property (nonatomic, strong) NSThread *thread2;@property (nonatomic, strong) NSThread *thread3;@property (nonatomic, assign) int leftTicketsCount;@property (nonatomic, strong) NSLock *lock;@end@implementation JHViewController- (void)viewDidLoad{ [super viewDidLoad]; self.leftTicketsCount = 100; self.thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(sale) object:nil]; self.thread1.name = @"售票员A"; self.thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(sale) object:nil]; self.thread2.name = @"售票员B"; self.thread3 = [[NSThread alloc] initWithTarget:self selector:@selector(sale) object:nil]; self.thread3.name = @"售票员C"; self.lock = [[NSLock alloc] init];}-(void)sale{ while (1) {// @synchronized (self.lock){ // 加锁 int count = self.leftTicketsCount; if (count > 0) { [NSThread sleepForTimeInterval:0.02]; self.leftTicketsCount = count - 1; NSThread *current = [NSThread currentThread]; NSLog(@"%@ 卖了一张 还剩下 %d张", current.name,self.leftTicketsCount); } else { [NSThread exit]; }// } // 解锁 }}-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ [self.thread1 start]; [self.thread2 start]; [self.thread3 start];}@end
通过运行打印 我们知道有重复的数值。这就是抢夺同一资源的问题。至于解决方法就是往其加锁。打开上面代码注释边即可。
- 线程间通信
定义:线程往往不是孤立存在,多个线程之间需要经常进行通信。
例如:下面子线程和主线程之间的切换。
#import "JHViewController.h"@interface JHViewController ()@property (weak, nonatomic) IBOutlet UIImageView *imageView;@end@implementation JHViewController- (void)viewDidLoad{ [super viewDidLoad];}-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ // 下载图片 (开启子线程) [self performSelectorInBackground:@selector(download) withObject:nil];}/** * 下载图片 : 子线程 */-(void)download{ // 根据URL下载图片 NSURL *url = [NSURL URLWithString:@"www.baidu.com"]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:data]; // 回到主线程 [self performSelectorOnMainThread:@selector(settingImage:) withObject:image waitUntilDone:NO];// [self.imageView performSelectorOnMainThread:@selector(settingImage:) withObject:image waitUntilDone:NO];}/** * 显示图片: 主线程 */-(void)settingImage:(UIImage *)image;{ self.imageView.image = image;}@end
- GCD “牛逼的中枢调度器”
优势:
苹果公司为多核的并行运算提出的解决方法
GCD会自动利用更多的CPU内核
GCD会自动管理线程的生命周期
程序员只告诉GCD想要执行什么任务,无需写线程管理代码
GCD的使用步骤:1.定制任务 2.将任务添加到队列中(fifo 先进先出)
GCD中有2个用来执行任务的函数:
1、用同步的方式执行任务 :dispatch_sync;
2、用异步的方式执行任务:dispatch_async;
延时执行:
1、调用NSObject的方法[self performSelector:withObject:afterDelay:];
2、使用GCD函数 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
});
一次性代码:
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
});
常见术语解释 同步.异步.并发.串行:
^ 同步:在当前线程中执行任务,不具备开启新线程能力
^异步:在新的线程中执行任务,具备开启新线程能力
^并发:多个任务同时执行
^串行:一个任务执行完后,再执行下一个任务
同步函数和异步函数:
同步函数
1.并发队列:不会开线程
2.串行队列:不会开线程
异步函数:
1.并发队列:能开N条线程
2.串行队列:开启一条线程
如果有什么建议 请联系虾米:QQ:584837022
微信:foreverlovewillgoon
1 0
- iOS开发学习之多线程
- IOS开发之多线程
- iOS开发之多线程
- iOS开发之多线程
- iOS开发之多线程
- iOS开发之多线程
- iOS开发之多线程
- iOS开发之多线程
- iOS开发之多线程
- iOS学习之多线程
- IOS开发之多线程(转)
- iOS之多线程开发小结
- IOS开发之多线程使用
- IOS开发之多线程详解
- iOS开发之多线程基础
- iOS开发之多线程NSThread
- iOS开发之多线程GCD
- iOS开发之多线程NSOperation
- iOS 开发OC语言(六) Block语法简介
- Spring AOP使用@AspectJ实现日志管理
- solr安装过程中遇到的问题和解决方案
- netbeans 新建代码模板
- 测试要知道的HTTP三种缓存方式
- iOS开发学习之多线程
- UNIX环境高级编程——进程(二)
- 理论: 图论(2): 拓扑排序
- c++基本知识(1)
- 水仙花 - %的两种用法
- setValue: forKey 和 setObject: forkey的区别
- Day6-二维数组,冒泡排序解析,数组为参数的传递
- English in December
- <LeetCode OJ> 232. Implement Queue using Stacks