【iOS开发-91】GCD的同步异步串行并行、NSOperation和NSOperationQueue一级用dispatch_once实现单例

时间:2023-07-03 08:48:19

(1)GCD实现的同步异步、串行并行。

——同步sync应用场景:用户登录,利用堵塞

——串行异步应用场景:下载等耗时间的任务

/**
* 由于是异步。所以开通了子线程。可是由于是串行队列,所以仅仅须要开通1个子线程(2),它们在子线程中顺序运行。 最经常使用。
*/
-(void)gcdDemo1{
dispatch_queue_t q1=dispatch_queue_create("com.hellocation.gcdDemo", DISPATCH_QUEUE_SERIAL);
for (int i=0; i<10; i++) {
dispatch_async(q1, ^{
NSLog(@"%@",[NSThread currentThread]);
});
}
}
/**
* 由于是异步。所以开通了子线程,且由于是并行队列,所以开通了好多个子线程,详细几个,无人知晓,看运气。 线程数量无法控制,且浪费。
*/
-(void)gcdDemo2{
dispatch_queue_t q2=dispatch_queue_create("com.hellocation.gcdDemo", DISPATCH_QUEUE_CONCURRENT);
for (int i=0; i<10; i++) {
dispatch_async(q2, ^{
NSLog(@"%@",[NSThread currentThread]);
});
}
}
/**
* 由于是同步,所以不管是并行队列还是串行队列,都是在主线程中运行
*/
-(void)gcdDemo3{
dispatch_queue_t q1=dispatch_queue_create("com.hellocation.gcdDemo", DISPATCH_QUEUE_SERIAL);
for (int i=0; i<10; i++) {
dispatch_sync(q1, ^{
NSLog(@"%@",[NSThread currentThread]);
});
}
}
/**
* 全局队列和并行队列相似(全局队列不须要创建直接get就可以,而导致其没有名字。不利于兴许调试)
*/
-(void)gcdDemo5{
dispatch_queue_t q=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i=0; i<10; i++) {
dispatch_sync(q, ^{
NSLog(@"%@",[NSThread currentThread]);
});
}
for (int i=0; i<10; i++) {
dispatch_async(q, ^{
NSLog(@"%@",[NSThread currentThread]);
});
}
}
/**
* 由于是主线程。所以异步任务也会在主线程上运行(1)。 而假设是同步任务,则堵塞了。由于主线程一直会在运行。所以后米的任务永远不会被运行。
* 主要用处,是更新UI。更新UI一律在主线程上实现
*/
-(void)gcdDemo6{
dispatch_queue_t q=dispatch_get_main_queue();
for (int i=0; i<10; i++) {
dispatch_sync(q, ^{
NSLog(@"%@",[NSThread currentThread]);
});
}
// for (int i=0; i<10; i++) {
// dispatch_async(q, ^{
// NSLog(@"%@",[NSThread currentThread]);
// });
// }
}

(2)NSOperation和NSOperationQueue实现的线程管理

/**
* 1、仅仅要是自己创建的队列,加入进来的操作(此处是block操作),都在子线程上(2)
* 2、仅仅要是在主队列中,加入进来的操作,都在主线程上(1)
* 两个队列不能同一时候抢一个任务操作
*/
-(void)opDemo1{
NSOperationQueue *queue=[[NSOperationQueue alloc]init];
NSBlockOperation *b=[NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@",[NSThread currentThread]);
}];
[queue addOperation:b];
[[NSOperationQueue mainQueue]addOperation:b];
}
/**
* 同上
*/
-(void)opDemo2{
NSInvocationOperation *i=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(helloWorld) object:nil];
NSOperationQueue *queue=[[NSOperationQueue alloc]init];
[queue addOperation:i];
[[NSOperationQueue mainQueue]addOperation:i];
} -(void)helloWorld{
NSLog(@"hello,world!");
}
/**
* 依赖关系:(1)能够保证运行顺序,也使得开的子线程不会太多;(2)能够跨队列。而串行是不能够跨队列的,如最后更新UI则变成在主队列中。
* 这是NSOperation(NSBlockOperation和NSInvocationOperation)和NSOperationQueue的优势
*/
-(void)opDemo3{
NSBlockOperation *op1=[NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片 %@",[NSThread currentThread]);
}];
NSBlockOperation *op2=[NSBlockOperation blockOperationWithBlock:^{
NSLog(@"修饰图片 %@",[NSThread currentThread]);
}];
NSBlockOperation *op3=[NSBlockOperation blockOperationWithBlock:^{
NSLog(@"保存图片 %@",[NSThread currentThread]);
}];
NSBlockOperation *op4=[NSBlockOperation blockOperationWithBlock:^{
NSLog(@"更新UI %@",[NSThread currentThread]);
}];
[op4 addDependency:op3];
[op3 addDependency:op2];
[op2 addDependency:op1];
NSOperationQueue *queue=[[NSOperationQueue alloc]init];
//设置同一时刻最大开启的线程数,这是NSOperationQueue特有的
[queue setMaxConcurrentOperationCount:2];
[queue addOperation:op1];
[queue addOperation:op2];
[queue addOperation:op3];
[[NSOperationQueue mainQueue]addOperation:op4];
}

(3)单例的实现(手写单例要求)dispatch_once运用。即重写类的allocWithZone方法

@implementation WPObject
+(instancetype)allocWithZone:(struct _NSZone *)zone{
static WPObject *insta;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
insta=[super allocWithZone:zone];
});
return insta;
}
@end