iOS 多线程笔记

153 阅读3分钟

GCD

同步函数

dispatch_sync(queue, ^{
    NSLog(@"---download1---%@",[NSThread currentThread]);
});

异步函数,具有开启线程的能力

dispatch_async(queue, ^{
    NSLog(@"---download1---%@",[NSThread currentThread]);
});

串行队列,任务串行执行

dispatch_queue_t queue = dispatch_queue_create("queueID", DISPATCH_QUEUE_SERIAL);

并行队列,任务可并发执行

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

全局并发队列

dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

主队列

dispatch_queue_t queue =  dispatch_get_main_queue();

任务并发执行必须并发队列 + 异步函数

dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 或者
//dispatch_queue_t queue = dispatch_queue_create("queueID", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
    NSLog(@"---download1---%@",[NSThread currentThread]);
});
    
dispatch_sync(queue, ^{
    NSLog(@"---download2---%@",[NSThread currentThread]);
});
    
dispatch_sync(queue, ^{
    NSLog(@"---download3---%@",[NSThread currentThread]);
});

队列组:多个任务执行完成再做其他操作。

//创建队列组
dispatch_group_t group =  dispatch_group_create();
dispatch_group_async(group, queue, ^{
    NSLog(@"任务1");
});
  
//下载图片2
dispatch_group_async(group, queue, ^{
    NSLog(@"任务2");
});
    
//合成
dispatch_group_notify(group, queue, ^{
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"%@--刷新UI",[NSThread currentThread]);
    });
});

快速迭代

dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index){
    // 执行10次代码,index顺序不确定
});

栅栏函数:等栅栏函数前的任务执行完再执行后面的任务

//1.创建队列(并发队列)
dispatch_queue_t queue = dispatch_queue_create("com.downloadqueue", DISPATCH_QUEUE_CONCURRENT);
    
dispatch_async(queue, ^{
    
    for (NSInteger i = 0; i<10; i++) {
        NSLog(@"%zd-download1--%@",i,[NSThread currentThread]);
    }
});
    
dispatch_async(queue, ^{
    
    for (NSInteger i = 0; i<10; i++) {
        NSLog(@"%zd-download2--%@",i,[NSThread currentThread]);
    }
});
    
//栅栏函数
dispatch_barrier_async(queue, ^{
    NSLog(@"我是一个栅栏函数");
});
    
dispatch_async(queue, ^{
    
    for (NSInteger i = 0; i<10; i++) {
        NSLog(@"%zd-download3--%@",i,[NSThread currentThread]);
    }
});
    
dispatch_async(queue, ^{
    
    for (NSInteger i = 0; i<10; i++) {
        NSLog(@"%zd-download4--%@",i,[NSThread currentThread]);
    }
});

NSOperation:抽象类,需要使用它的子类

// NSInvocationOperation
/*
 第一个参数:目标对象
 第二个参数:该操作要调用的方法,最多接受一个参数
 第三个参数:调用方法传递的参数,如果方法不接受参数,那么该值传nil
 */
NSInvocationOperation *operation = [[NSInvocationOperation alloc]
                                    initWithTarget:self selector:@selector(run) object:nil];

//2.启动操作
[operation start];

// NSBlockOperation
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    //在主线程中执行
    NSLog(@"---download1--%@",[NSThread currentThread]);
}];
    
//2.追加操作,追加的操作在子线程中执行
[operation addExecutionBlock:^{
    NSLog(@"---download2--%@",[NSThread currentThread]);
}];
    
//3.启动执行操作
[operation start];

默认情况下,调用实例对象的start方法并不会开启新线程执行任务,而需要将其加入NSOperationQueue中。

//1.创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    
//2.封装操作
NSInvocationOperation *op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download1) object:nil];
    
NSInvocationOperation *op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download2) object:nil];
    
//3.把封装好的操作添加到队列中
[queue addOperation:op1];//会自动执行[op1 start]
[queue addOperation:op2];

设置最大并发数

非主队列中的任务默认是并发执行的,可以通过设置队列的最大并发数来控制该队列中的任务是并发执行还是串行执行的.
当最大并发数==1 任务串行执行
当最大并发数>1 任务并发执行
系统默认的最大并发数 == -1 (默认是并发执行的)
当最大并发数 == 0 不会执行任务操作

//0.创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
queue.maxConcurrentOperationCount = 1;

取消队列中的所有任务

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

队列的暂停和恢复

暂停队列的时候,不能暂停当前正在执行的任务,当前任务还是会继续执行完,但是下一个任务将不会执行。
暂停操作是可以恢复的。

NSOperationQueue *queue = [[NSOperationQueue alloc]init];
// 暂停
queue.suspended = YES;
// 恢复
queue.suspended = NO;

操作依赖:操作A执行完后,才能执行操作B

//1.创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
NSOperationQueue *queueOther = [[NSOperationQueue alloc]init];

NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"download1 ---%@",[NSThread currentThread]);
}];
    
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"download2 ---%@",[NSThread currentThread]);
}];
//操作监听,当对应的任务执行完毕后,可以在block里面执行相关的扫尾操作
op2.completionBlock = ^{
    
    //注意:执行该block块代码的线程和执行op2操作的线程不一定一致,使用GCD和NSOperation技术线程的分配是系统内部决定的
    NSLog(@"任务op2已经执行完毕--%@",[NSThread currentThread]);
};

NSBlockOperation *op01 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"任务01---%@",[NSThread currentThread]);
}];
    
NSBlockOperation *op02 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"任务02---%@",[NSThread currentThread]);
}];

[op1 addDependency:op2];
//跨队列依赖
[op1 addDependency:op01];
[op02 addDependency:op1];

// 添加操作到相应的队列
[queue addOperation:op1];
[queue addOperation:op2];
    
[queueOther addOperation:op01];
[queueOther addOperation:op02];