(由于合在一起感觉一篇太长翻着累)
iOS多线程目前总结了四篇
欢迎移步O(∩_∩)O
目录
- GCD
- 队列
dispatch_queue_t
- 线程的开辟与阻塞机制
- 一次性代码(单例)
- 队列组
- GCD定时器
- 快速遍历
dispatch_apply
- 信号量
- 线程栅栏
- GCD的API
- 队列
GCD
队列dispatch_queue_t
GCD中有两种队列、并且每种队列都有两种创建方式(系统默认+自定义)
-
串行队列
1、主队列:
dispatch_get_main_queue()
2、自定义队列(串行):(参数为优先级、第二个参数DISPATCH_QUEUE_SERIAL
实际上是指向'NULL'的宏)
dispatch_queue_create("queue_name", DISPATCH_QUEUE_SERIAL)
-
并行队列
1、全局队列:(参数为优先级、第二个参数为0)
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
2、自定义队列(并行):
dispatch_queue_create("ss_queue", DISPATCH_QUEUE_CONCURRENT)
可以看出来、自定义队列都是使用dispatch_queue_create('队列名','队列类型')
进行创建。
线程的开辟与阻塞机制
- 并行和串行主要影响:任务的执行方式
并行:多个任务并发(同时)执行
串行:一个任务执行完毕后,再执行下一个任务
- 同步和异步主要影响:能不能开启新的线程
同步:在当前线程中执行任务,不具备开启新线程的能力
异步:在新的线程中执行任务,具备开启新线程的能力
-
会开辟新线程的两种情况
- 并行队列+异步任务 = 多条新线程
- 自定义串行多列+异步任务 = 一条新线程
其余情况、全部将会置于当前线程/主线程(主队列任务)下执行。
用我们常用的代码举个例子:
dispatch_queue_t q = dispatch_queue_create("test.q", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(q, ^{
for (int i = 0; i < 100000; i ++) {
NSLog(@"2--%d----%@",i,[NSThread currentThread]);
sleep(3);
}
});
dispatch_async(q, ^{
for (int i = 0; i < 100000; i ++) {
NSLog(@"1---%d----%@",i,[NSThread currentThread]);
sleep(3);
}
});
打印结果:
2018-03-19 15:32:12.591483+0800 test[5002:479872] 1---0----<NSThread: 0x600000278140>{number = 4, name = (null)}
2018-03-19 15:32:12.591549+0800 test[5002:479875] 2--0----<NSThread: 0x60400027b240>{number = 3, name = (null)}
2018-03-19 15:32:15.595894+0800 test[5002:479872] 1---1----<NSThread: 0x600000278140>{number = 4, name = (null)}
2018-03-19 15:32:15.595894+0800 test[5002:479875] 2--1----<NSThread: 0x60400027b240>{number = 3, name = (null)}
2018-03-19 15:32:18.601144+0800 test[5002:479872] 1---2----<NSThread: 0x600000278140>{number = 4, name = (null)}
2018-03-19 15:32:18.601144+0800 test[5002:479875] 2--2----<NSThread: 0x60400027b240>{number = 3, name = (null)}
这就是上面所说的并行队列+异步任务 = 多条新线程
。
如果我们把DISPATCH_QUEUE_CONCURRENT
换成DISPATCH_QUEUE_SERIAL
打印结果又会变成
2018-03-19 15:40:20.491705+0800 test[5083:493760] 2--0----<NSThread: 0x600000278d00>{number = 3, name = (null)}
2018-03-19 15:40:23.493296+0800 test[5083:493760] 2--1----<NSThread: 0x600000278d00>{number = 3, name = (null)}
2018-03-19 15:40:26.497652+0800 test[5083:493760] 2--2----<NSThread: 0x600000278d00>{number = 3, name = (null)}
所有的输出都集中在number = 3的新线程中。
一次性代码(单例)
static id obj = nil;
+ (NSObject *)getObj
{
static NSObject* obj;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
obj = [[NSObject alloc]init];
});
return obj;
}
-
dispatch_once
的实现原理
- (NSObject *)getObj
{
static NSObject* obj;
static dispatch_once_t onceToken;
NSLog(@"1::::%ld",onceToken);
dispatch_once(&onceToken, ^{
NSLog(@"2::::%ld",onceToken);
obj = [[NSObject alloc]init];
NSLog(@"3::::%ld",onceToken);
});
NSLog(@"4::::%ld",onceToken);
return obj;
}
打印结果:
2018-03-20 18:08:04.066961+0800 test[5861:729479] 1::::0
2018-03-20 18:08:04.067124+0800 test[5861:729479] 2::::768
2018-03-20 18:08:04.067256+0800 test[5861:729479] 3::::768
2018-03-20 18:08:04.067355+0800 test[5861:729479] 4::::-1
所以
- 当onceToken == 0 的时候、才允许进入函数内部执行初始化的block。
- block执行完将onceToken修改。
- (稍微扩展一下啊)当多个线程同时调用
dispatch_once
方法的时候、内部会借用信号量来进行线程控制、进一步保证每个block代码只执行一次。
更多的查看GCD外传:dispatch_once(上)、细说@synchronized和dispatch_once
队列组dispatch_group
//队列组
- (void)dispatch_group_test {
dispatch_queue_t queue = dispatch_queue_create("queue_test", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
NSLog(@"任务1——准备休眠3秒");
sleep(3);
NSLog(@"任务1——完成");
});
NSLog(@"主线程——准备休眠5秒");
sleep(5);
NSLog(@"主线休眠结束");
dispatch_group_async(group, queue, ^{
NSLog(@"任务2——准备休眠10秒");
sleep(10);
NSLog(@"任务2——完成");
});
dispatch_group_notify(group, queue, ^{
NSLog(@"任务组完成");
});
NSLog(@"主线程结束");
}
打印结果:
2018-03-20 10:43:32.135642+0800 test[1763:94602] 主线程——准备休眠5秒
2018-03-20 10:43:32.135649+0800 test[1763:94645] 任务1——准备休眠3秒
2018-03-20 10:43:35.141269+0800 test[1763:94645] 任务1——完成
2018-03-20 10:43:37.137225+0800 test[1763:94602] 主线休眠结束
2018-03-20 10:43:37.137513+0800 test[1763:94602] 主线程结束
2018-03-20 10:43:37.137515+0800 test[1763:94645] 任务2——准备休眠10秒
2018-03-20 10:43:47.139737+0800 test[1763:94645] 任务2——完成
2018-03-20 10:43:47.140116+0800 test[1763:94645] 任务组完成
这里可以扩展一下任务组的机制
-
dispatch_group_notify
任务组的结束通知可以添加多次、并且会多次调用。 - 类似于NSOperation中的依赖、GCD的group监听是可以追加的。只要
任务组
中的任务没有全部完成
、group完成的监听
就不会被调用
、哪怕是后追加的任务。
//队列组
- (void)dispatch_group_test {
dispatch_queue_t queue = dispatch_queue_create("queue_test", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
NSLog(@"任务1——准备休眠3秒");
sleep(3);
NSLog(@"任务1——完成");
});
NSLog(@"添加完成监听");
dispatch_group_notify(group, queue, ^{
NSLog(@"任务组完成");
});
dispatch_group_async(group, queue, ^{
NSLog(@"任务2——准备休眠10秒");
sleep(10);
NSLog(@"任务2——完成");
});
NSLog(@"主线程结束");
}
打印结果
2018-03-20 10:49:16.192283+0800 test[1866:104770] 添加完成监听
2018-03-20 10:49:16.192284+0800 test[1866:104819] 任务1——准备休眠3秒
2018-03-20 10:49:16.192519+0800 test[1866:104770] 主线程结束
2018-03-20 10:49:16.192534+0800 test[1866:104930] 任务2——准备休眠10秒
2018-03-20 10:49:19.197851+0800 test[1866:104819] 任务1——完成
2018-03-20 10:49:26.198201+0800 test[1866:104930] 任务2——完成
2018-03-20 10:49:26.198583+0800 test[1866:104930] 任务组完成
- 任务组是可以跨队列监听的
所以、监听中的第二个参数(队列)到底是干嘛的~希望有大神指正
评论区已经有大神回复:
第二个参数决定了监听函数的callback将会在哪个队列执行。
比如你希望在异步任务完成之后、回到主线程刷新页面。
- (void)dispatch_group_test {
dispatch_queue_t queue = dispatch_queue_create("queue_test", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t queue2 = dispatch_queue_create("queue_test", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue2, ^{
NSLog(@"任务1——准备休眠3秒");
sleep(3);
NSLog(@"任务1——完成");
});
NSLog(@"添加完成监听");
dispatch_group_notify(group, queue, ^{
NSLog(@"任务组完成");
});
NSLog(@"主线程结束");
}
打印结果:
2018-03-20 13:06:11.267924+0800 test[2243:234892] 添加完成监听
2018-03-20 13:06:11.267935+0800 test[2243:235001] 任务1——准备休眠3秒
2018-03-20 13:06:11.268402+0800 test[2243:234892] 主线程结束
2018-03-20 13:06:14.269280+0800 test[2243:235001] 任务1——完成
2018-03-20 13:06:14.269575+0800 test[2243:235001] 任务组完成
快速遍历dispatch_apply
GCD提供了多线程快速遍历的方法。需要注意的是:
- 由于多线程遍历、输出的下标未必按照顺序排列。
- 本质上是一个同步任务、而内部会使用一个并行队列用异步任务进行遍历。(所以如果需要、需要在外部自己开辟一个新的异步任务)
- (void)dispatch_apply_test {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
dispatch_apply(10, queue, ^(size_t index) {
NSLog(@"%@-%ld",[NSThread currentThread],index);
sleep(10);
});
NSLog(@"任务完成");
});
NSLog(@"主线程结束");
}
打印结果:
2018-03-20 13:27:38.463507+0800 test[2491:271571] 主线程结束
2018-03-20 13:27:38.463630+0800 test[2491:271633] <NSThread: 0x60400026e180>{number = 3, name = (null)}-0
2018-03-20 13:27:38.463639+0800 test[2491:271928] <NSThread: 0x604000274680>{number = 4, name = (null)}-1
2018-03-20 13:27:38.463713+0800 test[2491:271932] <NSThread: 0x60000007ccc0>{number = 5, name = (null)}-2
2018-03-20 13:27:38.463715+0800 test[2491:271933] <NSThread: 0x60400026ecc0>{number = 6, name = (null)}-3
2018-03-20 13:27:48.468368+0800 test[2491:271932] <NSThread: 0x60000007ccc0>{number = 5, name = (null)}-6
2018-03-20 13:27:48.468368+0800 test[2491:271928] <NSThread: 0x604000274680>{number = 4, name = (null)}-4
2018-03-20 13:27:48.468382+0800 test[2491:271933] <NSThread: 0x60400026ecc0>{number = 6, name = (null)}-7
2018-03-20 13:27:48.468392+0800 test[2491:271633] <NSThread: 0x60400026e180>{number = 3, name = (null)}-5
2018-03-20 13:27:58.471068+0800 test[2491:271932] <NSThread: 0x60000007ccc0>{number = 5, name = (null)}-9
2018-03-20 13:27:58.471068+0800 test[2491:271933] <NSThread: 0x60400026ecc0>{number = 6, name = (null)}-8
2018-03-20 13:28:08.473167+0800 test[2491:271633] 任务完成
GCD定时器
不同于基于Runloop的NSTimer
。dispatch_source_t
不会因为子线程没有正在运行的Runloop而失效、循环引用、计时不准(每次runloop循环才会检查定时器是否需要被执行)等问题。
也有几个点需要注意:
-
source
最好被持有、不然在暂停dispatch_suspend
的时候可能会Crash。 - 暂停
dispatch_suspend
/开始resumeTimer
一定要成对使用、否则会Crash。 - 可
dispatch_source_t
并没有检查source
本身状态的API。
@interface ViewController ()
@property (nonatomic, strong) dispatch_source_t timer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 创建定时器,(dispatch_source_t本质是OC对象)
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
// 设置定时器的实践参数,时间参数一般是纳秒(1秒 == 10的9次方纳秒)为单位
// 何时开始
dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (ino64_t)(1.0 * NSEC_PER_SEC));
// 时间间隔
uint64_t interval = (uint64_t)(2.0 * NSEC_PER_SEC);
// 设置参数
dispatch_source_set_timer(self.timer, start, interval, 0);
// 设置回调,即设置需要定时器定时执行的操作
dispatch_source_set_event_handler(self.timer, ^{
NSLog(@"------");
});
// 启动定时器
dispatch_resume(self.timer);
}
//暂停
-(void) pauseTimer{
if(_timer){
dispatch_suspend(_timer);
}
}
//恢复
-(void) resumeTimer{
if(_timer){
dispatch_resume(_timer);
}
}
//销毁
-(void) stopTimer{
if(_timer){
dispatch_source_cancel(_timer);
_timer = nil;
}
}
@end
信号量
信号量类似于锁。
简单来讲 信号量为0则阻塞线程,大于0则不会阻塞。则我们通过改变信号量的值,来控制是否阻塞线程,从而达到线程同步
GCD中的信号量含有三个函数:
-
dispatch_semaphore_create
创建一个semaphore信号量 -
dispatch_semaphore_signal
发送一个信号让信号量+1 -
dispatch_semaphore_wait
如果信号量计数为0则阻塞等待、否则通过。
具体的使用举两个例子吧。
- GCD控制并发数
通过设置信号量初始值、达到GCD的并发。
// 创建队列组
dispatch_group_t group = dispatch_group_create();
// 创建信号量,并且设置值为10
dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < 100; i++)
{ // 由于是异步执行的,所以每次循环Block里面的dispatch_semaphore_signal根本还没有执行就会执行dispatch_semaphore_wait,从而semaphore-1.当循环10此后,semaphore等于0,则会阻塞线程,直到执行了Block的dispatch_semaphore_signal 才会继续执行
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_group_async(group, queue, ^{
NSLog(@"%i",i);
sleep(2);
// 每次发送信号则semaphore会+1,
dispatch_semaphore_signal(semaphore);
});
}
- 异步任务转同步
通过再方法末尾用信号量阻塞、直到异步请求完成后再通过。
配合GCD任务组、NSOperation的依赖。可以达到多网络请求后的同步操作。
- (void)request1{
//创建信号量并设置计数默认为0
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
NSString *url = [NSString stringWithFormat:@"%s","http://v3.wufazhuce.com:8000/api/channel/movie/more/0?platform=ios&version=v4.0.1"];
[manager GET:url parameters:nil progress:^(NSProgress * _Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSArray *data = responseObject[@"data"];
for (NSDictionary *dic in data) {
NSLog(@"请求1---%@",dic[@"id"]);
}
//计数加1
dispatch_semaphore_signal(semaphore);
//11380-- data.lastObject[@"id"];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"shibai...");
//计数加1
dispatch_semaphore_signal(semaphore);
}];
//若计数为0则一直等待
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
线程栅栏dispatch_barrier
线程栅栏可以阻塞某个queue
中任务的执行直到queue
中栅栏
之前的任务被执行完毕。
- (void)dispatch_barrier_test {
dispatch_queue_t queue = dispatch_queue_create("test_queue", DISPATCH_QUEUE_CONCURRENT);
for (int i = 1; i <= 3; i ++) {
dispatch_async(queue, ^{
sleep(3);
NSLog(@"任务%d结束",i);
});
}
NSLog(@"代码经过栅栏");
dispatch_barrier_sync(queue, ^{
sleep(5);
NSLog(@"栅栏结束");
});
NSLog(@"代码通过栅栏");
for (int i = 4; i <= 6; i ++) {
dispatch_async(queue, ^{
sleep(3);
NSLog(@"任务%d结束",i);
});
}
NSLog(@"代码结束");
}
打印结果:
2018-03-20 16:44:07.347195+0800 test[4987:607391] 代码经过栅栏
2018-03-20 16:44:10.351954+0800 test[4987:607438] 任务1结束
2018-03-20 16:44:10.351954+0800 test[4987:607439] 任务3结束
2018-03-20 16:44:10.351984+0800 test[4987:607440] 任务2结束
2018-03-20 16:44:15.353557+0800 test[4987:607391] 栅栏结束
2018-03-20 16:44:15.353836+0800 test[4987:607391] 代码通过栅栏
2018-03-20 16:44:15.354086+0800 test[4987:607391] 代码结束
2018-03-20 16:44:18.357376+0800 test[4987:607441] 任务5结束
2018-03-20 16:44:18.357369+0800 test[4987:607440] 任务4结束
2018-03-20 16:44:18.357457+0800 test[4987:607438] 任务6结束
将同步栅栏dispatch_barrier_sync
换成异步栅栏dispatch_barrier_async
2018-03-20 16:45:52.798543+0800 test[5025:610657] 代码经过栅栏
2018-03-20 16:45:52.798700+0800 test[5025:610657] 代码通过栅栏
2018-03-20 16:45:52.798823+0800 test[5025:610657] 代码结束
2018-03-20 16:45:55.798703+0800 test[5025:610699] 任务1结束
2018-03-20 16:45:55.798722+0800 test[5025:610702] 任务3结束
2018-03-20 16:45:55.798725+0800 test[5025:610698] 任务2结束
2018-03-20 16:46:00.800958+0800 test[5025:610698] 栅栏结束
2018-03-20 16:46:03.805894+0800 test[5025:610701] 任务6结束
2018-03-20 16:46:03.805886+0800 test[5025:610698] 任务4结束
2018-03-20 16:46:03.805987+0800 test[5025:610702] 任务5结束
很明显的区别在于
- 同步栅栏会阻塞之后普通代码的执行、异步栅栏则不会。
应用线程栅栏的特性、我们可以更好的做一些线程同步。某些情况下不需要写好几层任务组来同步任务。
例如4/5/6任务想要等待1/2/3任务。
用任务组的的话、需要一个任务组包含(1/2/3)。
然后在任务组完成的回调中再并发出三个任务(4/5/6)。
而且还无法控制线程的阻塞、除非在想要阻塞的地方加入最后一个同步任务。
想想就很麻烦....
GCD的API
这部分不是我自己写的、在查阅一些API资料的途中翻到了这篇博客。
《iOS多线程之GCD》深表感谢。
/*
功能:将块函数添加到线程队列中异步执行(异步:执行后不管结果直接返回)
参数:queue:指定的队列 block/work 块函数(context:传入block块函数中的参数)
返回值:空
*/
void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
void dispatch_async_f(dispatch_queue_t queue,
void *_Nullable context,
dispatch_function_t work);
/*
功能:将块函数添加到线程队列中同步执行(异步:执行完成后返回结果)
参数:queue:指定的队列 block/work 块函数(context:传入block块函数中的参数)
返回值:空
*/
void dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
void dispatch_sync_f(dispatch_queue_t queue,
void *_Nullable context,
dispatch_function_t work);
/*
功能:将块函数添加到线程队列中按照迭代次数执行,所有迭代完成后返回结果
参数:iterations:迭代次数 queue:指定的队列 block/work 块函数(context:传入block块函数中的参数)
返回值:空
*/
void dispatch_apply(size_t iterations, dispatch_queue_t queue,
DISPATCH_NOESCAPE void (^block)(size_t));
dispatch_apply_f(size_t iterations, dispatch_queue_t queue,
void *_Nullable context,
void (*work)(void *_Nullable, size_t));
/*
功能:获取当前执行中的队列
参数:无
返回值:当前队列或者空
*/
dispatch_queue_t dispatch_get_current_queue(void);
/*
功能:获取主队列
参数:无
返回值:主队列或者空
*/
dispatch_queue_t dispatch_get_main_queue(void)
{
return DISPATCH_GLOBAL_OBJECT(dispatch_queue_t, _dispatch_main_q);
}
/*
功能:获取全局并发队列
参数:identifier:队列优先级 typedef long dispatch_queue_priority_t;
- DISPATCH_QUEUE_PRIORITY_HIGH: QOS_CLASS_USER_INITIATED
- DISPATCH_QUEUE_PRIORITY_DEFAULT: QOS_CLASS_DEFAULT
- DISPATCH_QUEUE_PRIORITY_LOW: QOS_CLASS_UTILITY
- DISPATCH_QUEUE_PRIORITY_BACKGROUND: QOS_CLASS_BACKGROUND
#define DISPATCH_QUEUE_PRIORITY_HIGH 2
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0
#define DISPATCH_QUEUE_PRIORITY_LOW (-2)
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN
flags:保留供将来使用,输入除了0以外的任何值可能返回空值
返回值:全局队列或者空
*/
dispatch_queue_t dispatch_get_global_queue(long identifier, unsigned long flags);
#define DISPATCH_QUEUE_SERIAL NULL //串行队列
#define DISPATCH_QUEUE_SERIAL_INACTIVE//暂停状态串行队列
dispatch_queue_attr_make_initially_inactive(DISPATCH_QUEUE_SERIAL)
#define DISPATCH_QUEUE_CONCURRENT //并发队列
DISPATCH_GLOBAL_OBJECT(dispatch_queue_attr_t, _dispatch_queue_attr_concurrent)
#define DISPATCH_QUEUE_CONCURRENT_INACTIVE //暂停状态并发队列
dispatch_queue_attr_make_initially_inactive(DISPATCH_QUEUE_CONCURRENT)
/*
功能:设置属性值,用于在队列的创建时加入
参数:attr:队列属性值
返回值:队列属性值
*/
dispatch_queue_attr_t dispatch_queue_attr_make_initially_inactive(
dispatch_queue_attr_t _Nullable attr);
#define DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL
dispatch_queue_attr_make_with_autorelease_frequency(
DISPATCH_QUEUE_SERIAL, DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM)
#define DISPATCH_QUEUE_CONCURRENT_WITH_AUTORELEASE_POOL
dispatch_queue_attr_make_with_autorelease_frequency(
DISPATCH_QUEUE_CONCURRENT, DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM)
dispatch_queue_attr_t dispatch_queue_attr_make_with_autorelease_frequency(
dispatch_queue_attr_t _Nullable attr,
dispatch_autorelease_frequency_t frequency);
/*
功能:创建队列
参数:label:队列附带信息,可有可无 attr:队列属性值 target:目标队列,相当于目标队列计数加一
返回值:引用的队列
*/
dispatch_queue_t dispatch_queue_create(const char *_Nullable label,
dispatch_queue_attr_t _Nullable attr);
dispatch_queue_t dispatch_queue_create_with_target(const char *_Nullable label,
dispatch_queue_attr_t _Nullable attr, dispatch_queue_t _Nullable target)
/*
功能:获取队列描述信息
参数:label:队列附带信息,可有可无 attr:队列属性值 target:目标队列,相当于目标队列计数加一
返回值:队列附带信息
*/
const char *dispatch_queue_get_label(dispatch_queue_t _Nullable queue);
//dispatch_qos_class_t dispatch_queue_get_qos_class(dispatch_queue_t queue,
int *_Nullable relative_priority_ptr);
/*
功能:给指定对象设置目标队列
参数:object:目标对象 queue:目标队列
返回值:无
*/
void dispatch_set_target_queue(dispatch_object_t object,
dispatch_queue_t _Nullable queue);
/*
功能:dispatch类入口函数
参数:无
返回值:无
*/
void dispatch_main(void);
/*
功能:在指定时间后再目标队列执行block任务
参数:when:时间 queue:目标队列 block/work:要执行的任务 context:传入任务中的参数
返回值:无
*/
void dispatch_after(dispatch_time_t when,
dispatch_queue_t queue,
dispatch_block_t block);
void dispatch_after_f(dispatch_time_t when,
dispatch_queue_t queue,
void *_Nullable context,
dispatch_function_t work);
/*
功能:给指定队列增加一个阻塞其它异步执行任务的任务
参数:queue:队列 block/work:任务 context:传入任务的参数
返回值:无
*/
void dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
void dispatch_barrier_async_f(dispatch_queue_t queue,
void *_Nullable context,
dispatch_function_t work);
/*
功能:给指定队列增加一个阻塞其它同步执行任务的任务
参数:queue:队列 block/work:任务 context:传入任务的参数
返回值:无
*/
void dispatch_barrier_sync(dispatch_queue_t queue,
DISPATCH_NOESCAPE dispatch_block_t block);
void dispatch_barrier_sync_f(dispatch_queue_t queue,
void *_Nullable context,
dispatch_function_t work);
/*
功能:当指定队列键值改变时,或者是所有属性值都释放后,调用销毁函数destructor
参数:queue:队列 key:键名 context:新内容 destructor:销毁函数
返回值:无
*/
void dispatch_queue_set_specific(dispatch_queue_t queue, const void *key,
void *_Nullable context, dispatch_function_t _Nullable destructor);
/*
功能:获取指定队列特定键内容
参数:queue:队列 key:键名
返回值:键值
*/
void *_Nullable dispatch_queue_get_specific(dispatch_queue_t queue, const void *key);
/*
功能:获取当前队列特定键内容
参数: key:键名
返回值:键值
*/
void *_Nullable dispatch_get_specific(const void *key);
/*
功能:验证当前块任务运行在指定队列上
参数:queue:队列
返回值:无
*/
void dispatch_assert_queue(dispatch_queue_t queue)
DISPATCH_ALIAS_V2(dispatch_assert_queue);
/*
功能:验证当前块任务运行在指定队列上,并且该任务阻塞队列中的其它任务
参数:queue:队列
返回值:无
*/
void dispatch_assert_queue_barrier(dispatch_queue_t queue);
/*
功能:验证当前块任务没有运行在指定队列上
参数:queue:队列
返回值:无
*/
void dispatch_assert_queue_not(dispatch_queue_t queue)
DISPATCH_ALIAS_V2(dispatch_assert_queue_not);
/******************************************************dispatch—group****************************************************/
/*
功能:创建派遣队列组
参数:无
返回值:队列组
*/
dispatch_group_t dispatch_group_create(void);
/*
功能:给指定队列添加异步执行任务,将队列加入组
参数:group:队列组 queue:指定队列 block/work:任务 context:传入任务的参数
返回值:无
*/
void dispatch_group_async(dispatch_group_t group,
dispatch_queue_t queue,
dispatch_block_t block);
void dispatch_group_async_f(dispatch_group_t group,
dispatch_queue_t queue,
void *_Nullable context,
dispatch_function_t work);
/*
功能:等待(阻塞线程)一直到(队列组中所有任务执行结束或者是时间结束)
参数:group:队列组 timeout:时间
返回值:0表示成功,非0.错误
*/
long dispatch_group_wait(dispatch_group_t group, dispatch_time_t timeout);
/*
功能:队列组中所有任务执行结束之后,执行新的block 任务
参数:group:任务组 queue:指定队列 block/work:新任务 context:传入任务的参数
返回值:任务组
*/
void dispatch_group_notify(dispatch_group_t group,
dispatch_queue_t queue,
dispatch_block_t block);
void dispatch_group_notify_f(dispatch_group_t group,
dispatch_queue_t queue,
void *_Nullable context,
dispatch_function_t work);
/*
功能:管理显示队列组中所有任务
参数:group:队列组
返回值:队列组
*/
void dispatch_group_enter(dispatch_group_t group);
/*
功能:管理显示队列组中以执行结束的任务
参数:group:队列组
返回值:队列组
*/
void dispatch_group_leave(dispatch_group_t group);
/******************************************************dispatch—semaphore****************************************************/
/*
功能:创建信号量
参数:value:信号量资源数
返回值:信号量或空(失败)
*/
dispatch_semaphore_t dispatch_semaphore_create(long value);
/*
功能:等待获取信号量,获取到后开始继续执行,或是时间结束
参数:dsema:信号量 timeout:限定时间
返回值:无
*/
long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);
/*
功能:执行结束,不需要占用资源,释放信号量
参数:dsema:信号量
返回值:无
*/
long dispatch_semaphore_signal(dispatch_semaphore_t dsema);
/******************************************************dispatch—object****************************************************/
/*
功能:增加队列引用计数
参数:object:操作队列
返回值:无
*/
void dispatch_retain(dispatch_object_t object);
/*
功能:减少队列引用计数
参数:object:操作队列
返回值:无
*/
void dispatch_release(dispatch_object_t object);
/*
功能:获取对象应用程序上下文
参数:object:对象
返回值:定义内容或空
*/
void *_Nullable dispatch_get_context(dispatch_object_t object);
/*
功能:设置指定对象的应用程序上下文
参数:object:对象 context:上下文内容
返回值:无
*/
void dispatch_set_context(dispatch_object_t object, void *_Nullable context);
/*
功能:设置对象销毁函数,在该对象所有引用释放后,销毁该对象
参数:object:对象 finalizer:销毁函数指针
返回值:无
*/
void dispatch_set_finalizer_f(dispatch_object_t object,
dispatch_function_t _Nullable finalizer);
/*
功能:激活指定非活动对象
参数:object:对象(一般是线程队列)
返回值:无
*/
void dispatch_activate(dispatch_object_t object);
/*
功能:挂起/阻塞指定对象(一般是线程队列)
参数:object:对象
返回值:无
*/
void dispatch_suspend(dispatch_object_t object);
/*
功能:恢复指定对象(一般是线程队列)
参数:object:对象
返回值:无
*/
void dispatch_resume(dispatch_object_t object);
/*
功能:同步等待一个对象完成操作,或者是直到超出规定时间
参数:object:对象 timeout:限定时间
返回值:0成功,非0失败
*/
long dispatch_wait(void *object, dispatch_time_t timeout);
/*
功能:在指定对象完成工作后,将一个通知块任务加入指定队列
参数:object:对象 queue:队列 notification_block:通知块
返回值:无
*/
void dispatch_notify(void *object, dispatch_object_t queue,
dispatch_block_t notification_block);
/*
功能:取消指定对象
参数:object:对象
返回值:无
*/
void dispatch_cancel(void *object);
/*
功能:判断指定对象是否被取消
参数:object:对象
返回值:0表示未取消,其它表示取消
*/
long dispatch_testcancel(void *object);
/*
功能:已编程方式记录指定对象的调试调度信息
参数:object:对象
返回值:无
*/
void dispatch_debug(dispatch_object_t object, const char *message, ...);
void dispatch_debugv(dispatch_object_t object, const char *message, va_list ap);
/******************************************************dispatch—once****************************************************/
/*
功能:只执行任务函数一次
参数:predicate:dispatch_once_t 对象 block/function要执行的任务函数 context:传入的内容
返回值:无
*/
void dispatch_once(dispatch_once_t *predicate,
DISPATCH_NOESCAPE dispatch_block_t block);
void dispatch_once_f(dispatch_once_t *predicate, void *_Nullable context,
dispatch_function_t function);
/******************************************************dispatch—time****************************************************/
/*
功能:创建时间对象,在指定时间的基础上再添加一段时间
参数:when:时间 delta:时间段(纳秒)
返回值:时间对象
*/
dispatch_time_t dispatch_time(dispatch_time_t when, int64_t delta);
/*
功能:创建时间对象,在指定时间的基础上再添加一段时间
参数:when:时间 delta时间段(纳秒)
返回值:时间对象
*/
dispatch_time_t dispatch_walltime(const struct timespec *_Nullable when, int64_t delta);
最后
本文主要是自己的学习与总结。如果文内存在纰漏、万望留言斧正。如果不吝赐教小弟更加感谢。