iOS学习

多线程

2016-08-18  本文已影响42人  iOS_Alex

多线程

进程和线程

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];

通过NSObjectNSThread类别方法创建

//多线程中执行方法

[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];

上一篇 下一篇

猜你喜欢

热点阅读