ios基础篇(十三)—— 调度组、NSOperationQueue

el/2023/6/4 14:55:23

一、调度组

  • 有时候需要在多个异步任务都执行完成之后继续做某些事情,比如下载歌曲,等所有的歌曲都下载完毕之后 转到 主线程提示用户
//1 全局队列dispatch_queue_t queue = dispatch_get_global_queue(0, 0);//2 调度组dispatch_group_t group = dispatch_group_create();//3 添加任务//把任务添加到队列,等任务执行完成之后通知调度组dispatch_group_async(group, queue, ^{NSLog(@"歌曲1  %@",[NSThread currentThread]);});dispatch_group_async(group, queue, ^{NSLog(@"歌曲2  %@",[NSThread currentThread]);});dispatch_group_async(group, queue, ^{NSLog(@"歌曲3  %@",[NSThread currentThread]);});//4 所有任务都执行完成后,获得通知 (异步执行)//等调度组中队列的任务完成后,把block添加到指定的队列
//    dispatch_group_notify(group, queue, ^{
//        NSLog(@"okkkkkkk   %@",[NSThread currentThread]);
//    });dispatch_group_notify(group, dispatch_get_main_queue(), ^{
//更新UI控件,提示用户NSLog(@"okkkkkkk   %@",[NSThread currentThread]);});NSLog(@"over");

调度组原理

在终端中 输入man dispatch_group_async
//1 全局队列dispatch_queue_t queue = dispatch_get_global_queue(0, 0); //2 调度组dispatch_group_t group = dispatch_group_create(); //ARC中不用写
//    dispatch_retain(group);//3 进入调度组,执行此函数后,再添加的异步执行的block都会被group监听dispatch_group_enter(group);    //4 添加任务dispatch_async(queue, ^{NSLog(@"!!--!!");dispatch_group_leave(group);//ARC中此行不用写,也不能写
//        dispatch_release(group);});dispatch_group_enter(group);dispatch_async(queue, ^{NSLog(@"!!------!!");dispatch_group_leave(group);//ARC中此行不用写,也不能写//dispatch_release(group);});//5  获得调度组的通知dispatch_group_notify(group, dispatch_get_main_queue(), ^{NSLog(@"okkkkkkk   %@",[NSThread currentThread]);});
//6 等待调度组 监听的队列中的所有任务全部执行完毕,才会执行后续代码,会阻塞线程(很少使用)
//下载三首歌曲,当歌曲都下载完毕 通知用户
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {[self demo2];
}
//调度组内部的原理
- (void)demo2 {//创建组dispatch_group_t group = dispatch_group_create();//创建队列dispatch_queue_t queue = dispatch_queue_create("hm", DISPATCH_QUEUE_CONCURRENT);   //任务1dispatch_group_enter(group);dispatch_async(queue, ^{     NSLog(@"任务1");dispatch_group_leave(group);});    //任务2dispatch_group_enter(group);dispatch_async(queue, ^{      NSLog(@"任务2");dispatch_group_leave(group);});//任务3dispatch_group_enter(group);dispatch_async(queue, ^{[NSThread sleepForTimeInterval:2.0];NSLog(@"任务3");dispatch_group_leave(group);});   //等待组中的任务都执行完毕,才会执行dispatch_group_notify(group, dispatch_get_main_queue(), ^{NSLog(@"over");});//等待组中的任务都执行完毕,才会继续执行后续的代码dispatch_group_wait(group, DISPATCH_TIME_FOREVER);NSLog(@"hello ");
}
//演示调度组的基本使用
- (void)demo1 {//创建组dispatch_group_t group = dispatch_group_create();//队列dispatch_queue_t queue = dispatch_get_global_queue(0, 0);//下载第一首歌曲dispatch_group_async(group, queue, ^{NSLog(@"正在下载第一个歌曲");});   //下载第二首歌曲dispatch_group_async(group, queue, ^{NSLog(@"正在下载第二个歌曲");[NSThread sleepForTimeInterval:2.0]; });//下载第三首歌曲dispatch_group_async(group, queue, ^{NSLog(@"正在下载第三个歌曲");});   //当三个异步任务都执行完成,才执行dispatch_group_notify(group, dispatch_get_main_queue(), ^{NSLog(@"over %@",[NSThread currentThread]);});  
}

二、NSOperation

  • NSOperation的作用
    • 是OC语言中基于GCD的面向对象的封装
    • 使用起来比GCD更加简单(面向对象)
    • 提供了一些用GCD不好实现的功能
    • 苹果推荐使用,使用NSOperation不用关心线程以及线程的生命周期

  • 查看NSOperation的头文件
    • NSOperation是一个抽象类
      • 不能直接使用(方法没有实现)
      • 约束子类都具有共同的属性和方法
    • NSOperation的子类
      • NSInvocationOperation
      • NSBlockOperation
      • 自定义operation
  • NSOperationQueue队列

使用步骤

  • NSOperation和NSOperationQueue实现多线程的具体步骤
    1. 先将需要执行的操作封装到一个NSOperation对象中
    2. 然后将NSOperation对象添加到NSOperationQueue中
      • 系统会自动将NSOperationQueue中的NSOperation取出来
      • 将取出的NSOperation封装的操作放到一条新线程中执行

  • 建NSInvocationOperation对象
- (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;
  • 调用start方法开始执行操作
- (void)start;

一旦执行操作,就会调用target的sel方法

   注意

  1. 默认情况下,调用了start方法后并不会开一条新线程去执行操作,而是在当前线程同步执行操作
  2. 只有将NSOperation放到一个NSOperationQueue中,才会异步执行操作。
  • 创建NSBlockOperation对象
+ (id)blockOperationWithBlock:(void (^)(void))block;
  • 通过addExecutionBlock:方法添加更多的操作
- (void)addExecutionBlock:(void (^)(void))block;

注意:只要NSBlockOperation封装的操作数 > 1,就会异步执行操作

三、NSOperationQueue

  • NSOperationQueue的作用

NSOperation可以调用start方法来执行任务,但默认是同步执行的

如果将NSOperation添加到NSOperationQueue(操作队列)中,系统会自动异步执行NSOperation中的操作

  • 添加操作到NSOperationQueue中
- (void)addOperation:(NSOperation *)op;
- (void)addOperationWithBlock:(void (^)(void))block;
@interface ViewController ()
//全局队列
@property (nonatomic, strong) NSOperationQueue *queue;
@end@implementation ViewController
//懒加载
- (NSOperationQueue *)queue {if (_queue == nil) {_queue = [[NSOperationQueue alloc] init];}return _queue;
}
//演示start
- (void)demo1 {//创建操作NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{NSLog(@"hello %@",[NSThread currentThread]);}];//更新op的状态,执行main方法[op start];  //不会开新线程
}
//把操作添加到队列
- (void)demo2 {//创建队列NSOperationQueue *queue = [[NSOperationQueue alloc] init];//创建操作NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{NSLog(@"hello %@",[NSThread currentThread]);}];//把操作添加到队列中[queue addOperation:op];
}
- (void)demo3 {NSOperationQueue *queue = [[NSOperationQueue alloc] init];[queue addOperationWithBlock:^{NSLog(@"hello %@",[NSThread currentThread]);}];
}
//全局队列
- (void)demo4 {    
//    //并发队列,异步执行
//    for (int i = 0; i < 10; i++) {
//        [self.queue addOperationWithBlock:^{
//            NSLog(@"hello %d  %@",i,[NSThread currentThread]);
//        }];
//    }
}
// 操作的 completionBlock
- (void)demo5 {NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{[NSThread sleepForTimeInterval:2];NSLog(@"hello %@",[NSThread currentThread]);}];//操作完成之后执行[op setCompletionBlock:^{NSLog(@"end %@",[NSThread currentThread]);}];    [self.queue addOperation:op];
}

四、线程间通信

  • 主队列
    • 添加到主队列的操作,最终都执行在主线程上
    • [NSOperationQueue mainQueue]
  • 当前队列
    • 获取当前操作所在的队列
    • [NSOperationQueue currentQueue]
  • 模拟当图片下载完成后回归到主线程上更新UI
@interface ViewController ()
//全局队列
@property (nonatomic, strong) NSOperationQueue *queue;
@end@implementation ViewController
//懒加载
- (NSOperationQueue *)queue {if (_queue == nil) {_queue = [[NSOperationQueue alloc] init];}return _queue;
}
- (void)viewDidLoad {[super viewDidLoad];   [self.queue addOperationWithBlock:^{//异步下载图片NSLog(@"异步下载图片");        //获取当前队列
//        [NSOperationQueue currentQueue]       //线程间通信,回到主线程更新UI[[NSOperationQueue mainQueue] addOperationWithBlock:^{NSLog(@"更新UI");}];}];
}
1 消息循环主线程的消息循环默认开启,子线程的消息循环默认不开启
2 消息循环的目的保证程序不退出负责处理输入事件
3 输入事件和消息循环的模式输入事件的模式必须跟当前消息循环的模式匹配,输入事件才会执行
4 子线程消息循环  run
5 GCD队列  串行队列 并行队列  全局(并行)队列 主队列任务执行  同步执行  异步执行
6 各种组合6.1 串行队列同步执行   不开线程,顺序执行异步执行   开一个线程,顺序执行6.2 并行队列(全局队列)同步执行   不开线程,顺序执行异步执行   开多个线程,无序执行6.3 主队列同步执行   在主线程上执行的话会死锁异步执行   主线程,顺序执行
7 Barrier 阻塞     多线程中操作线程不安全的类,要小心
8 after 延迟执行
9 once 一次性执行 线程安全的单例  保证一个程序中只有一份单例对象(工具类)
10 调度组 让多个异步任务 都完成之后做一件事情
11 NSOperation 抽象类  抽象类中的方法都没有实现,等待子类去实现(约束子类)NSInvocationOperationNSBlockOperationstart 不开线程  会设置操作的状态  会调用main操作添加到队列 --  并行队列,异步执行  开多个线程,无序执行
12 NSOperationQueue

 

http://www.ngui.cc/el/3419341.html

相关文章

ios基础篇(十五)—— SDWebImage

一、SDWebImage介绍 什么是SDWebImage iOS中著名的牛逼的网络图片处理框架包含的功能&#xff1a;图片下载、图片缓存、下载进度监听、gif处理等等用法极其简单&#xff0c;功能十分强大&#xff0c;大大提高了网络图片的处理效率国内超过90%的iOS项目都有它的影子项目地址 ht…

ios基础篇(十六)—— 网络之sockct

一、网络基本概念 客户端&#xff1a;应用 C/S B/S服务器&#xff1a;为客户端提供服务、数据、资源的机器请求&#xff1a;客户端向服务器索取数据响应&#xff1a;服务器对客户端的请求作出反应&#xff0c;一般是返回给客户端数据服务器 内网服务器外网服务器本地测试服…

时序图

一、时序图简介&#xff08;Brief introduction&#xff09; 时序图&#xff08;Sequence Diagram&#xff09;是显示对象之间交互的图&#xff0c;这些对象是按时间顺序排列的。 顺序图中显示的是参与交互的对象及其对象之间消息交互的顺序。 时序图中包括的建模元素主要有&a…

《Objective-C高级编程:iOS与OS X多线程和内存管理》 一 自动引用计数

一、自动引用计数 1.1 内存管理的思考方式 对象操作与objective-c 方法的对应对象操作Object-C 方法生成并持有对象alloc、new、copy、mutableCopy持有对象retain方法释放对象release方法废弃对象dealloc方法1.1.1 自己生成的对象&#xff0c;自己持有 使用以下名称开头的方…

《Objective-C高级编程:iOS与OS X多线程和内存管理》 一 Blocks模式GCD

一、Blocks摘要 Blocks&#xff1a;带有自动变量&#xff08;局部变量&#xff09;的匿名函数。 匿名函数&#xff1a;不带有名称的函数。 int func(int cout); //声明名称为func的函数 int result func(10); // 调用该函数&#xff0c;必须使用该函数的名称 // 若像下面这…

JXCategoryTitleView的使用

最近写项目&#xff0c;遇到了一个vc下面有多个vc 指示器可以点击切换&#xff0c;也可也左右滑动进行切换&#xff0c;解除了JXCategoryTitleView 感觉很好用&#xff1b; 一般要求主vc遵循JXCategoryViewDelegate、JXCategoryListContainerViewDelegate两个协议 子vc遵循JX…

基本编程能力练习

一、首先下载Java的编译环境并安装 JDK下载地址&#xff1a;https://www.oracle.com/java/technologies/javase-jdk15-downloads.html 选择适合自己系统的版本进行安装 这里我选择的是jdk-15_windows-x64_bin.exe 下载完成后直接运行安装&#xff0c;安装位置选择默认的C盘&am…

基本任务1.1Java语言基础

一、任务要求 完成基本数据类型的使用。完成基本运算符和表达式的使用。完成基本控制语句&#xff1a;判断、分支、循环等语句的使用。完成数组的使用。所有源代码必须加入行一级注释。 二、任务的理解 本次任务是让我们对Java编程中所遇到的基础知识进行学习和掌握&#xf…

基本任务1.1Java语言基础(任务挑战)

任务挑战&#xff1a; 1.编制一个Java application应用程序&#xff0c;把数组中已知的10个数字由小到大排序后输出。 编程前思考&#xff1a; 完成数组排序的方法有多种&#xff0c;其中有调用Arrays类中的sort方法直接对数组进行由小到大的排序&#xff0c;还可以采用冒泡排序…

基本任务1.2Java面向对象程序

一、任务要求 完成一个Java application应用程序&#xff0c;描述一个人类。要求如下&#xff1a;要求此人类必须包含有人的姓名、性别、出生日期等基本属性&#xff08;变量&#xff09;。要求此人类描述吃饭的方法&#xff08;函数&#xff09;和描述睡觉的方法&#xff08;…