• 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(),^{

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

    })

    }

    }];



  • 相关阅读:
    导包路径
    django导入环境变量 Please specify Django project root directory
    替换django的user模型,mysql迁移表报错 django.db.migrations.exceptions.InconsistentMigrationHistory: Migration admin.0001_initial is applied before its dependen cy user.0001_initial on database 'default'.
    解决Chrome调试(debugger)
    check the manual that corresponds to your MySQL server version for the right syntax to use near 'order) values ('徐小波','XuXiaoB','男','1',' at line 1")
    MySQL命令(其三)
    MySQL操作命令(其二)
    MySQL命令(其一)
    [POJ2559]Largest Rectangle in a Histogram (栈)
    [HDU4864]Task (贪心)
  • 原文地址:https://www.cnblogs.com/zhoulina/p/5503632.html
Copyright © 2020-2023  润新知