多线程
进程和线程
NSThread
通过类方法开启线程
通过NSObject的NSThread类别方法创建
注意!!
通过init方式创建线程
GCD
GCD的简单实用
GCD的队列种类
GCD为异步并行任务添加隔断barrier
UIWebView
简单实用
常用方法
在info.plist文件中修改以支持iOS的Http
关于性能优化的一个小点
时间戳
多线程
多线程的实现方式:
1.pThread: 最早期,纯C的,兼容所有C语言基础的代码 2.NSThread: 本质上是使用OC对pThread的一个封装, 是早期iOS使用的多线程
3.GCD: 使用C语法+block语法, 目前为止苹果主推的多线程技术,功能强大,效率高
4.NSOperation: 使用OC对于GCD的一个封装, 在GCD基础上额外增加了几个特性, 不过效率没有GCD高.
通常在不使用这些特性时,依然选择GCD
进程和线程
进程: 当应用程序运行起来以后, 就称为一个进程(进行中的程序)
线程: 进程的任务,工作 必须在线程中进行
进程就好像申请了一个道路, 线程就是车, 任务就是人, 任务的执行就是人上车 --> 到达目的地
主线程: 主路, 优先级最高的, 当CPU资源有限时,会优先进行主线程上的任务..
苹果规定所有能被用户察觉的操作, 都应该放到主线程上, 所有UI视图都应该在主线程中执行
分线程: 辅路, 要必然主路. 非UI的都可以放到分线程执行
NSThread
通过类方法开启线程
//参数3: 方法的参数, 这里的方法是无参数方法, 不用传递, 参数是id类型, 什么都能传递
[NSThreaddetachNewThreadSelector:@selector(wasteTime) toTarget:selfwithObject:nil];
通过NSObject的NSThread类别方法创建
//多线程中执行方法
[selfperformSelectorInBackground:@selector(wasteTime) withObject:nil];
//从子线程回归主线程
//参数3: 表示是否等待此操作完毕, 再继续执行下方的方法
[v performSelectorOnMainThread:@selector(removeFromSuperview) withObject:nilwaitUntilDone:YES];
注意!!
凡是用户可见的操作, 必须在主线程中执行!!, 否则报错或者根本无效
通过init方式创建线程
//自定义化最强的开启线程的方法
NSThread*thread = [[NSThreadalloc] initWithTarget:selfselector:@selector(wasteTime) object:nil];
//定义某个线程的名字
thread.name=@"分线程";
//设置线程的优先级
/* 由高 到 低
和图形处理相关的任务, 比如滚动 动画 等.
NSQualityOfServiceUserInteractive
用户请求的任务, 但是不需要特别精确处理.
NSQualityOfServiceUserInitiated
周期性的用户请求任务, 比如每5分钟查收一次新邮件, 如果系统繁忙, 中间少几次, 用户也无法察觉
NSQualityOfServiceUtility
比如说一些后台优化, 电子邮件App对邮件进行索引以方便搜索
NSQualityOfServiceBackground
NSQualityOfServiceDefault
*/
thread.qualityOfService=NSQualityOfServiceDefault;
//需要手动启动
[thread start];
GCD
GCD: Grand Central Dispatch
是用于取代NSThread的多线程解决方案, 是Apple独有的
属于轻量级的, 占用资源少. 是目前iOS平台主流的多线程解决方案
同步: 同与主线程, 就是主线程上运行 sync
异步: 已于主线程, 就是分线程 async
串行: 多个任务同时执行 serial, 理解为 排队上公交, 有先后
效率低, 有序
并行: 多个任务在不同线程执行 concurrent 理解为不排队上公交,谁先上去 各看本领
效率高, 无序
GCD的简单实用
任务队列: 串行队列 并行队列. 用于存放任务的
同步异步: 任务队列运行的位置, 主线程还是分线程
步骤: 创建队列->任务放队列里->队列放到线程中执行
//异步串行
//非主线程执行 有序的任务
- (IBAction)asycnSerial:(id)sender {
//创建一个串行的任务队列queue队列
dispatch_queue_tqueue = dispatch_queue_create("Serial", DISPATCH_QUEUE_SERIAL);
//dispatch_async(queue, block) 代表把参数block中的代码 放在 quque中 异步(async)执行
//任务1: 打印0~9
dispatch_async(queue, ^{
for(inti =0; i <10; i++) {
NSLog(@"%d, %@", i, [NSThreadcurrentThread]);
}
});
//任务2: 打印A到K
dispatch_async(queue, ^{
for(inti ='A'; i <='K'; i++) {
NSLog(@"%c, %@", i, [NSThreadcurrentThread]);
}
});
}
//异步并行
- (IBAction)asyncConcurrent:(id)sender {
//创建并行队列
dispatch_queue_tquque = dispatch_queue_create("Concurrent", DISPATCH_QUEUE_CONCURRENT);
//异步添加 任务 打印0~9 到并行队列中
dispatch_async(quque, ^{
for(inti =0; i <10; i++) {
NSLog(@"%d, %@", i, [NSThreadcurrentThread]);
}
});
//异步添加 任务 打印A~K 到并行队列中
dispatch_async(quque, ^{
for(inti ='A'; i <'K'; i++) {
NSLog(@"%c, %@", i, [NSThreadcurrentThread]);
}
});
}
//同步并行
- (IBAction)syncConcurrent:(id)sender {
//执行效果,虽然是并行队列, 但是因为添加到了主线程中,线程有硬性规定, 同一时间只能做一个任务
//创建并行队列
dispatch_queue_tquque = dispatch_queue_create("Concurrent", DISPATCH_QUEUE_CONCURRENT);
//把任务添加到并行队列中, 在同步(主线程)中执行0~9
dispatch_sync(quque, ^{
for(inti =0; i <10; i++) {
NSLog(@"%d, %@", i, [NSThreadcurrentThread]);
}
});
//把任务添加到并行队列中, 在同步(主线程)中执行A~K
dispatch_sync(quque, ^{
for(inti ='A'; i <'K'; i++) {
NSLog(@"%c, %@", i, [NSThreadcurrentThread]);
}
});
}
//同步串行
- (IBAction)syncSerial:(id)sender {
//创建串行队列
dispatch_queue_tqueue = dispatch_queue_create("Serial", DISPATCH_QUEUE_SERIAL);
//把任务1放到串行队列中 同步(主线程)执行0~9
dispatch_sync(queue, ^{
for(inti =0; i <10; i++) {
NSLog(@"%d, %@", i, [NSThreadcurrentThread]);
}
});
//把任务2放到串行队列中 同步(主线程)执行A~K
dispatch_sync(queue, ^{
for(inti ='A'; i <'K'; i++) {
NSLog(@"%c, %@", i, [NSThreadcurrentThread]);
}
});
}
GCD的队列种类
GCD 队列类型一共分为3种:
1. 自建队列 通过dispatchqueuecreate创建
2. 主队列: 主线程上默认创建的队列--串行
3. 全局队列: 系统默认提供的专门存放 异步任务的队列-并行
//异步全局队列
- (IBAction)asyncGlobalQueue:(id)sender {
//dispatch_queue_t queue = dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0);
//dispatch_queue_t queue1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//参数1:在iOS8之后有更新, 从宏定义方式变为了枚举类型
//参数2:现在没用, 以后可能有用.(自己看头文件注释)
dispatch_queue_tqueue = dispatch_get_global_queue(0,0);
dispatch_async(queue, ^{
for(inti =0; i <10; i++) {
NSLog(@"%d , %@", i, [NSThreadcurrentThread]);
}
/* 这样放, 就自然串行了
for (int i = 'A'; i < 'K'; i++) {
NSLog(@"%c , %@", i, [NSThread currentThread]);
}*/
});
dispatch_async(queue, ^{
for(inti ='A'; i <'K'; i++) {
NSLog(@"%c , %@", i, [NSThreadcurrentThread]);
}
});
}
//异步主队列: 任务会在主线程中执行
//这种做法十分常用, 专门用于在子线程中回归到主线程
- (IBAction)asyncMainQueue:(id)sender {
dispatch_queue_tquque = dispatch_get_main_queue();
dispatch_async(quque, ^{
for(inti =0; i <10; i++) {
NSLog(@"%d, %@", i, [NSThreadcurrentThread]);
}
});
dispatch_async(quque, ^{
for(inti ='A'; i <'K'; i++) {
NSLog(@"%c, %@", i, [NSThreadcurrentThread]);
}
});
}
//同步主队列
- (IBAction)syncMainQueue:(id)sender {
//任务1: 向主队列中添加新任务 --- 发生在主队列
//任务2: 打印 .... , --- 发生在主队列
/*
公交车原则: 不到站不开门
1.公交车要到站 开门
2.中途有人要下车
司机: 您先下,顾客是上帝
顾客: 公司有规定, 您先开
车停了....
*/
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"....");
});
}
GCD为异步并行任务添加隔断barrier
通过添加barrier, 来让异步并行任务有了依赖关系, 某个并行任务的执行需要其他任务完成以后.
买吃的: 买一份煎饼+黄焖鸡上楼
通过添加 barrier(墙/隔断), 把煎饼和黄焖鸡作为一组, 当他们都完成以后, 再执行上楼
- (IBAction)asyncBarrier:(id)sender {
// 要加墙,必须使用自建并行队列
dispatch_queue_tqueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"购买黄焖鸡 %@", [NSThreadcurrentThread]);
//当前线程暂停2秒钟, 模仿制作过程
sleep(2);
NSLog(@"黄焖鸡购买完成");
});
dispatch_async(queue, ^{
NSLog(@"购买煎饼 %@", [NSThreadcurrentThread]);
//当前线程暂停3秒钟, 模仿制作过程
sleep(3);
NSLog(@"煎饼购买完成");
});
//希望上方两个任务都完成以后,再执行新的任务
dispatch_barrier_async(queue, ^{
NSLog(@"上楼");
sleep(3);
NSLog(@"到班级");
});
//吃
dispatch_async(queue, ^{
NSLog(@"开始吃黄焖鸡");
sleep(2);
NSLog(@"黄焖鸡吃完");
});
dispatch_async(queue, ^{
NSLog(@"开始吃煎饼");
sleep(3);
NSLog(@"煎饼吃完了");
});
}
UIWebView
简单实用
- (void)viewDidLoad {
[superviewDidLoad];
//加载百度网页
//URL 全球资源定位器
//必须写http://或者https://(安全),这表示链接地址遵循哪种协议
/*
FTP://获取网络文件
File://找本地文件的
*/
NSURL*url = [NSURLURLWithString:@"http://www.baidu.com"];
//iOS9新特性, 默认抵制不安全网络协议http://的, 可以通过修改info文件,来解决这个问题, 添加
NSURLRequest*request = [NSURLRequestrequestWithURL:url];
[_webView loadRequest:request];
}
常用方法
- (void)reload;//刷新
- (void)stopLoading;//停止刷新
- (void)goBack;//返回
- (void)goForward;//前进
在info.plist文件中修改以支持iOS的Http
控制台出现以下错误, 都是因为iOS9默认不支持http请求导致的
解决方法是
关于性能优化的一个小点
性能优化: 图片控件用代码添加, 如果是使用sb模式, 那么需要先把imageView拖拽到sb上,
不管用还是不用, 内存都会被imageView占用, 这是一个资源的消耗.
酷跑小人应该是只有点按钮以后,才显示. 才应该占据内存. 即 懒汉模式.
时间戳
某个时间到另一个时间的秒数(微秒数), 通常是指1970年到现在时间
NSDate提供了 当前时间到1970年的秒数, 这就是时间戳
//获取当前时间
NSDate*date = [NSDatedate];
//获取开始时,距离1970年的秒数
NSTimeIntervalbeginS = [date timeIntervalSince1970];