iOS多线程分析

进程

1.正在进行的一个过程或任务,负责任务执行的是cpu。
2.每个进程之间是独立的,每个进程都运行在独立的内存空间内,并拥有独立运行所需的全部资源。

线程

1.程序运行时的最小单位,是进程的实际运作单位。
2.进程想要执行任务必须至少有一个线程。在应用程序启动时,系统会默认开启一个线程,即主线程。

进程和线程的关系

1.线程在进程下进行
2.一个进程可以包含多个线程
3.同一个进程内不同的线程间数据容易共享
4.进程是用内存地址可以上锁,即一个线程使用共享内存时,其他线程必须等待其结束,才能使用。(互斥锁)
5.进程使用的内存地址也可以限定使用,即当前只允许2 人访问,第三人需要等待有人结束访问后再进行访问。(信号量)
6.一个程序有多个进程,一个进程可以有多个线程,但每个进程至少要有一个线程。

多线程

1.多条线程并发执行,cpu快速的在多条线程之间调度。 如果cpu调度线程时间足够的快,就造成了多线程并发的假象。
2.如果线程非常多,也会大量消耗cpu资源。
3.多线程可以提高程序的执行效率,能适当提高资源的利用率。
4.如果开启大量的线程会占用内存空间,降低程序性能。

队列

串行队列

同一时间内,队列中只能执行一个任务,当前任务结束后才能执行下一个任务。

并发队列

同时允许多个任务并发执行。

iOS中的多线程

GCD

1.获取主线程

dispatch_queue_t main_queue = dispatch_get_main();

2.线程延时

/** 
DISPATCH_TIME_NOW : 现在
DISPATCH_TIME_FOREVER : 永远超时
NSEC_PER_SEC : 秒  (1000,000,000 纳秒 = 1秒) 可精确到纳秒级,eg. 0.1 *  NSEC_PER_SEC 是0.1 * 1000,000,000 = 100,000,000 纳秒 = 0.1秒 以下算法雷同。
NSEC_PER_MSEC : 毫秒 (1000,000 纳秒  = 1 毫秒)可精确到毫秒级
USEC_PER_SEC : 秒   (1000000微秒 = 1秒) 可精确到微秒级
NSEC_PER_USEC : 微秒  (1000纳秒 = 1 微秒) 可精确到纳秒级
*/
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), main_queue, ^{
    NSLog(@"哈哈");
})

3.只执行一次,常用作单例模式

static dispatch_once_t once;
dispatch_once(&once, ^{
     // 只实例化一次
     personModel = [[self alloc] init];
 });

4.线程组,即等待一组任务完成后继续执行下一步,常被应用在图片上传

    // 开启全集并发线程,DISPATCH_QUEUE_PRIORITY_DEFAULT 是线程等级, 0 是flag,备用字段,通常设置0
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, queue, ^{
       // 进行操作1
    });
    dispatch_group_async(group, queue, ^{
       // 进行操作2
    });
    dispatch_group_async(group, queue, ^{
       // 进行操作3
    });
    
    dispatch_group_notify(group, queue, ^{
       // 操作1。2。3 执行完毕 进行 下一步操作
    });
    // 超时等待,即设置一个最长等待时常,超过时间后 调起 notify block
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

5.信号量,设置最大并发线程数,设置数大于1时顺序不能保证

//创建信号量, 2为设置最大并发线程
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
    for (int i = 0; i < 5; i++) {
        // 创建异步线程
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            // 信号量的等待时长,这里设置为一直等待,当信号量小于0 时一直等待,如果大于1则进入且降低信号量即-1
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            // 睡眠2秒
            sleep(2);
            // po 出当前线程, 显示log
            NSLog(@"%@", [NSThread currentThread]);
            // 标记信号量 + 1
            dispatch_semaphore_signal(semaphore);
            
        });
    }
    
    for (int i = 0; i < 5; i++) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            sleep(2);
            NSLog(@"%@", [NSThread currentThread]);
            dispatch_semaphore_signal(semaphore);
            
        });
    }

NSOPeration

NSOperation是基于GCD的抽象基类。
NSOperation可以跨队列设置依赖关系
NSOperation面向对象,支持KVO,可以检测operation是否正在执行,是否结束或者取消
NSOperation实体子类有两个,NSBlockOperation 和 NSInvocationOperation

    // 初始化 方法实例
    NSInvocationOperation *invoOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(haha:) object:nil];
    [invoOperation start];
    // 初始化 block块 实例
    NSBlockOperation *blockOpertaion = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"ni hao ");
    }];
// 继续添加线程
blockOperation add
    [blockOpertaion start];
    // 以下为 依赖关系
    // 获取 主线程
    NSOperationQueue *main_Operation = [NSOperationQueue mainQueue];
    // 创建 各种线程
    NSOperation *person_a = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"我是 神秘人 A");
    }];
    NSOperation *person_b = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"我是 神秘人 B");
    }];
    NSOperation *person_c = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"我是 神秘人 C");
    }];
    // 添加依赖关系, A以来 B和C ,相当于 A要在 B C 之后才能执行任务
    [person_a addDependency:person_b];
    [person_a addDependency:person_c];
    
    //添加到 主线程中 查看顺序
    [main_Operation addOperation:person_a];
    [main_Operation addOperation:person_b];
    [main_Operation addOperation:person_c];

NSThread

NSThread使用比较简单,可以静态获取线程信息

 // 获取主线程
    NSThread *thread = [NSThread mainThread];
    // 判断是否开启了多线程
    BOOL isOpenThread = [NSThread isMultiThreaded];
    // 获取当前线程
    NSThread *currentThread = [NSThread currentThread];
    // 当前线程睡眠 时间(s) 10秒钟
    [NSThread sleepForTimeInterval:10];
    //  睡眠到指定时间 , 以下为当前时间往后延10秒钟
    [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]];
    // 退出当前线程 , 禁止在主线程使用
    //[NSThread exit];

    // 初始化线程对象  实例化对象
    /*
     qualityOfService 线程的优先级
     NSQualityOfServiceUserInteractive 最高级别,用于UI交互,点击事件,绘制图形等
     NSQualityOfServiceUserInitiated = 次高级别,用于执行立即返回的任务
     NSQualityOfServiceUtility 普通级别,不需要立即返回的任务
     NSQualityOfServiceBackground 后台级别,完全不紧急的任务
     NSQualityOfServiceDefault 默认级别
     */
    NSLog(@"%@", [NSThread currentThread]);
    NSThread *asynThread = [[NSThread alloc] initWithTarget:self selector:@selector(hello) object:nil];
    // 设置 线程实例化对象的 优先级别,默认为 默认级别
    asynThread.qualityOfService = NSQualityOfServiceDefault;
    // 开始线程
    [asynThread start];
    
    // 也可以快速创建线程
    [NSThread detachNewThreadSelector:@selector(hello) toTarget:self withObject:nil];
    __weak typeof(self) weakSelf = self;
    [NSThread detachNewThreadWithBlock:^{
        // po 出当前线程
        NSLog(@"%@", [NSThread currentThread]);
        // 回到主线程
        [weakSelf performSelectorOnMainThread:@selector(hello) withObject:nil waitUntilDone:NO];
    }];

    // 还有一些 创建线程的方法
    // 3 秒后执行 hello 方法 , 在当前线程
    [self performSelector:@selector(hello) withObject:nil afterDelay:3];
    // 后台异步执行
    [self performSelectorInBackground:@selector(hello) withObject:nil];
    // 在主线程上执行 hello 方法
    [self performSelectorOnMainThread:@selector(hello) withObject:nil waitUntilDone:NO];
    // 在 指定的 asynThread 线程上执行 hello方法  *** 注意避免在子线程中执行 ui交互
    [self performSelector:@selector(hello) onThread:asynThread withObject:nil waitUntilDone:NO];

你可能感兴趣的:(iOS多线程分析)