多线程

作者: iOS_Alex | 来源:发表于2016-08-18 13:16 被阅读42次

    多线程

    进程和线程

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

    相关文章

      网友评论

        本文标题:多线程

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