zoukankan      html  css  js  c++  java
  • iOS-Senior10-多线程(子线程创建)

    1.多线程概述

    程序:由源代码生成的可执行应用。(eg:QQ.app)

    进程:一个正在运行的程序可以看做一个进程。(eg:正在运行的QQ就是一个进程),进程用用独立运行所需的全部资源。

    线程:程序中独立运行的代码段。(eg:接收QQ消息的代码)

    一个进程是由一或多个线程组成。进程只负责资源的调度和分配,线程才是程序真正的执行单元,负责代码的执行。

    1.1单线程

    每个正在运行的程序(即进程),至少包含一个线程,这个线程就叫主线程

    主线程在程序启动时被创建,用于执行main函数。

    只有一个主线程的程序,称为单线程程序。

    在单线程程序中,主线程负责执行程序的所有代码(UI展现以及刷新,网络请求,本地存储等等)。这些代码只能顺序执行,无法并发执行。

    1.2多线程

    拥有多个线程的程序,称作多线程程序。

    iOS中允许用户自己开辟新的线程,相对于主线程来讲,这些线程,称作子线程。

    可以根据需要开辟若干子线程。

    子线程和主线程都是独立的运行单元,各自执行互不影响,因此能够并发执行。

    1.3单线程和多线程的区别

    单线程程序:只有一个线程,即主线程,代码顺序执行,容易出现代码阻塞(页面假死)。

    多线程程序:有多个线程,线程间独立运行,能有效的避免代码阻塞,并且提高程序的运行性能。

    注意:iOS中关于UI的添加和刷新必须在主线程中操作。

    2.iOS平台下的多线程

    2.1NSThread

    方法:

    //初始化一个子线程,但需要手动开启

    - (id) initWithTarget : (id) target selector : (SEL)selector object :(id)argument

    //初始化一个子线程,并自动开启

    + (void) detachNewThreadSelector : (SEL) aSelector toTarget : (id) aTarget withObject :(id) anArgument

    //开启子线程

    start   [operation start]

    //取消当前子线程

    cancel [operation cancel]

    源代码:

    //手动开辟子线程

    NSThread *thread = [[NSThread alloc] initWithTarget : self selector:@selector(sayHi) object:nil];

    [thread start];

    //使用NSThread和NSObject实现的开辟线程,系统会自动释放,关不关都行

    [thread cancel]; 没有真正取消,而是给线程发送一个信号,通过这个信号进行取消的

    [thread exit];  直接将线程退出

    //自动开启子线程

    [NSThread detachNewThreadSelector:@selector(sayHi) toTarget:self withObject:nil];

    self.view.backgroundColor = [UIColor redColor] ;

    2.2NSObject

    //使用performSelectorInBackground开辟子线程

    [self performSelectorInBackground :@selector(sayHi) withObject:@"test"];

    //在子线程调用的方法里返回主线程,在调用另一个方法

    [self performSelectoraOnMainThread:@selector(mainThreadChangeColor) withObject :nil waitUntilDone: YES];

    - (void)mainThreadChangeColor {

    self.view.backgroudColor = [UIColor magentaColor];

    }

    方法:

    获取当前线程:[NSThread currentThread]

    获取主线程   :[NSThread mainThread]

    线程休眠2秒 :[NSThread sleepForTimeInterval:2]

    注意:

    1.每个线程都维护这与自己对应的NSAutoreleasePool对象,将其放在线程栈的栈顶。当线程结束时,会清空自动释放池。

    2.为保证对象的及时释放,在多线程方法中需要添加自动释放池。

    3.在应用程序打开的时候,系统会自动为主线程创建一个自动释放池。

    4.我们手动创建的子线程需要我们手动添加自动释放池。

    4.NSOperation和NSOperationQueue

    NSOperation类,在NVC中属于M,是用来封装单个任务相关的代码和数据的抽象类。

    因为它是抽象的,不能够直接使用这个类,而是使用子类(NSInvocation,NSBlockOperation)来执行实际任务。

    NSOperation(含子类),只是一个操作,本身无主线程,子线程之分,可在任意线程中使用。通常与NSOperationQueue结合使用。

    //NSInvocationOperation:封装了执行操作的target和要执行的action

    //NSBlockOperation:封装了需要执行的代码

    //NSOperation不能直接进行多线程的创建,需要借助:NSOperationQueue

    //在单独使用NSOperation的子类去创建线程的时候,一定要启动才行;

    //在使用NSOperation的子类去创建线程的时候,实际上线程没有真正意义上的创建

    源程序:

    NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test) object:nil];

    NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{

            NSLog(@"我是block");

            NSLog(@"+++++%@",[NSThread currentThread]);

            NSLog(@"*******%@",[NSThread mainThread]);

        }];

    - (void)test {

        NSLog(@"☺");

        NSLog(@"currentThread == %@",[NSThread currentThread]);

        NSLog(@"mainThread ==  %@",[NSThread mainThread]);

    }

        //借助队列,创建子线程

        NSOperationQueue *queue = [[NSOperationQueue alloc] init];

        [queue addOperation:operation];

        [queue addOperation:blockOperation]; //有addOperation的时候,就不可以用start,否则会造成崩溃

    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

        //创建队列的对象

        NSOperationQueue *queue = [[NSOperationQueue alloc] init];

        //最大的并发数量值

        //当值设置为1的时候,可以叫做串行(单线程)顺序执行

        queue.maxConcurrentOperationCount = 2;

        //当值设置大于1的时候,叫做并行:多条通道同时进行各自的任务

        for (int i = 0; i < 10; i++) {

            //创建10个线程

            NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{

                NSLog(@"currentThread == %@,mainThread == %@,%d",[NSThread currentThread],[NSThread mainThread],i);

             }];

            [queue addOperation:blockOperation];

     }

     }

    5.GCD(Grand Central Dispatch)使用

    简介:GCD是Apple开发的一种多核编程技术。主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。

    GCD提供函数实现多线程开发,性能更高,功能也更强大。

    它首次发布在Mac OS X 10.6,iOS4及以上也可以用。

    任务:具有一定功能的代码段。一般是一个block或者函数。

    分发队列:GCD以队列的方式进行工作,FIFO(先进先出)

    GCD会根据分发队列的类型,创建合适数量的线程执行队列中的任务。

    GCD中两种队列:

    1.SerialQueue:一次只执行一个任务。Serial queue通常用于通常用于同步访问特定的资源或数据。当你创建多个Serial queue时,虽然他们各自是同步执行的,但Serial queue与Serial queue之间是并发执行的。

    2.Concurrent:可以并发地执行多个任务,但是遵守FIFO

    #pragma mark - 使用GCD去创建一个串行队列

    //第一种:系统提供的创建串行队列的方法

    dispatch_queue_t queue = dispatch_get_main_queue();

    //在真正的开发中如果需要创建串行队列,比较习惯用这种

    //第二种:自己去创建

    dispatch_queue_t = dispatch_queue_create(DISPATCH_QUEUE_SERIAL,0);

    #pragma mark - 使用GCD去创建并行队列

    //第一种:系统的方式

    //参数1:优先级(有4个,没有明显的区别)

    dispatch_queue_t queue = dispatch_get_globel_queue(DISPATCH_QUEUE_PRIORITY);

    //第二种:自己定义的方式(参数和串行不一样)

    //参数1:表示创建队列的名字

    //参数2:系统提供的宏

    //创建队列

    dispatch_queue_t queue = dispatch_queue_create("myQueue",DISPATCH_QUEUE_CONCURRENT);

    //创建任务

    dispatch_async(queue,^{

    NSLog(@"current == %@",[NSThread currentThread]);

    NSLog(@"main == %@",[NSThread MainThread]);

    NSLog(@"我是任务一,子进程一");

    });

    dispatch_async(queue,^{

    NSLog(@"current == %@",[NSThread currentThread]);

    NSLog(@"main == %@",[NSThread MainThread]);

    NSLog(@"我是任务二,子进程二");

    });

    dispatch_async(queue,^{

    NSLog(@"current == %@",[NSThread currentThread]);

    NSLog(@"main == %@",[NSThread MainThread]);

    NSLog(@"我是任务三,子进程三");

    });

    #pragma mark - 几秒之后去做每一件事

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(3.0 * NSEC_PER_SEC)),dispatch_get_main_queue(),^{

    NSLog(@"3.0秒的时候");

    }

    );

    #pragma mark - 重复向一个队列中添加多个任务

    dispatch_queue_t queue = dispatch_queue_create(0,DISPATH_QUEUE_CONCURRENT);

    dispatch_apply(100,queue,^(size_t index)) {

    NSLog(@"index = %zu",index);

    }

    #pragma mark - 分组

    //创建一个分组

    dispatch_group_t group = dispatch_group_create();

    //创建一个并行队列

    dispatch_queue_t queue = dispatch_queue_create(0,DISPATCH_QUEUE_CONCURRENT);

    //创建任务1

    dispatch_group_asunc(group,queue,^{

    NSLog(@"我是任务1");

    });

    //创建任务2

    dispatch_group_asunc(group,queue,^{

    NSLog(@"我是任务2");

    });

    //创建任务3

    dispatch_group_asunc(group,queue,^{

    NSLog(@"我是任务3");

    });

    //用于监听所有任务的执行情况的,所以此功能代码必须放在所有任务之后进行书写的

    dispatch_group_notify(group,queue,^{

    NSLog(@"我是监听的,最后执行");

    });

    #pragma mark - 并发中的串行(披着羊皮的狼)

    //创建的串行队列

    dispatch_queue_t queue = dispatch_queue_create(0,DISPATH_QUEUE_CONCURRENT);

     

    dispatch_async(queue,^{

    NSLog(@"任务1");

    });

    dispatch_async(queue,^{

    NSLog(@"任务2");

    });

    dispatch_async(queue,^{

    NSLog(@"任务3");

    });

    #pragma mark - loadData

    //1.url

    NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];

    //2.session

    NSURLSession *session = [NSURLSession sharedSession];

    //3.task

    NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData *_NUllabel data,NSURLResponse *_Nullabel response,NSError *_Nullable error){

    if(error == nil){

    //处理数据

    //回到主线程刷新UI

    dispatch_async(dispatch_get_main_queue(),^{

    //自己灵活的写点东西吧!!!

    })

    }

    }];



  • 相关阅读:
    K8S 强制删除卡在Terminating状态的namespaces 记录
    docke 搭建 SVN服务器
    mysql-5.6--gtid主从配置
    keeplived + haproxy 高可用网络代理-安装配置 centos-7.6
    elasticsearch磁盘定时清理--转载
    HTTPS证书自动生成--certbot
    haproxy2.0-编译安装-centos7.6
    mongodb-定时按日期备份到json文件
    linux日志切割工具 logrotate
    mongodb--arbiter-集群安装
  • 原文地址:https://www.cnblogs.com/zhoulina/p/5503632.html
Copyright © 2011-2022 走看看