《iOS高级开发之多线程编程之三》
主队列上的同步异步执行
- 主队列 异步执行 在主线程有序执行
dispatch_queue_t queue = dispatch_get_main_queue();
for (int i = 0; i < 10; i++) {
dispatch_async(queue, ^{ NSLog(@"hello---%d %@",i,[NSThread currentThread]); }); }
文章图片
主队列 异步执行.png
- 主队列 同步执行 在主线程上执行时会死锁
dispatch_queue_t queue = dispatch_get_main_queue(); //测试执行 NSLog(@"begin"); for (int i = 0; i < 10; i++) { dispatch_sync(queue, ^{ NSLog(@"hello --- %@",[NSThread currentThread]); }); } //测试执行 NSLog(@"end");
文章图片
主队列 同步执行.png 分析
从运行结果可以明显看出,程序无法正常执行 被死锁。解决方案 (主队列 同步执行)放入异步执行,解决死锁问题
接下来看一下锁死的原因:
当程序运行到下面这段代码时
dispatch_sync(queue, ^{
NSLog(@"hello --- %@",[NSThread currentThread]);
});
主线程:如果主线程正在执行行代码,就不调度任务
同步执行: 如果第一个任务没有执行,就等待第一个任务执行完成后,在执行下一个任务。导致程序互相等待,造成死锁。
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_queue_t queue1 = dispatch_get_global_queue(0, 0);
//测试执行
NSLog(@"begin");
dispatch_async(queue1, ^{
for (int i = 0;
i <10;
i++) {
dispatch_sync(queue, ^{
NSLog(@"hello---%d %@",i,[NSThread currentThread]);
});
}
});
//测试执行
NSLog(@"end");
文章图片
Snip20170409_6.png 知识拓展
- 主队列于串行队列的区别
- 串行队列: 必须的一个任务调度完成,再去执行另一个任务
- 主队列: 以先进先出的调度任务,如果主线程上有任务在执行,主队列不会调用任务
- NSOperation是一个抽象的类
- 不能直接使用(方法没有实现)
- 结束子类都具有共同的属性和方法
- NSOperation的子类
- NSInvocationOperation
- NSBlockOperation
- 自定义operation
- NSOperationQueue队列
- NSInvocationOperation
- 新建一个NSInvocationOperation对象
- (id)initWithTarget:(id)target selector:(SEL)sel object:(nullable id)arg;
- 调用start方法开始执行操作
- (void) start;
一旦执行操作,就回到用start 的sel方法
默认情况下,调用start方法并不会开一条新线程执行操作,而是在当前线程同步执行操作,只有将一个NSOperation放到NSOperationQueue中,才会异步执行操作接下来我们来测试一下
- (void)viewDidLoad {
[super viewDidLoad];
//NSInvocationOperation操作
//创建操作
NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(diown) object:nil];
//创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//异步执行
[queue addOperation:operation];
//同步执行 }
-(void) diown{
NSLog(@"download --- %@",[NSThread currentThread]);
}
文章图片
Snip20170409_7.png
可以看出,在子线程中执行的。如果没有将NSOperation放到NSOperationQueue中,将会同步执行,这里不做演示了
- NSBlockOperation
- 【《iOS高级开发之多线程编程之三》】新建一个 NSBlockOperation对象
+ (instancetype)blockOperationWithBlock:(void (^)(void))block;
*创建addExecutionBlock:方法添加更多操作
- (void)addExecutionBlock:(void (^)(void))block;
注意
只要NSBlockOperation封装的操作 >1 就会执行,异步操作接下来我们来测试一下
NSBlockOperation *operation = [[NSBlockOperation alloc]init];
[operation addExecutionBlock:^{
NSLog(@"----下载图片--1---%@",[NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"----下载图片--2---%@",[NSThread currentThread]);
}];
[operation start];
文章图片
Snip20170409_8.png
- NSOperationQueue
NSOperation可以调用start方法来调用任务,但是默认是同步执行。如果将NSOperation添加到NSOperationQueue的队列中,系统会自动,异步执行
- NSOperationQueue的作用
- 添加操作到NSOperationQueue中
- (void)addOperation:(NSOperation *)op;
- (void)addOperationWithBlock:(void (^)(void))block ;
下面将演示这两种不同的添加方式
- 第一种
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
NSInvocationOperation *op = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(deom) object:nil];
[op start];
[queue addOperation:op];
- (void) demo{
NSLog(@"%@",[NSThread currentThread]);
}
- 第二种(创建全程队列)--相比第一种,这一种更为简便
@interface ViewController ()
//创建一个全程队列
@property (nonatomic, strong) NSOperationQueue *queue;
@end
//懒加载
- (NSOperationQueue *)queue{
if (_queue == nil) {
_queue = [[NSOperationQueue alloc]init];
}
return _queue;
}
[self.queue addOperationWithBlock:^{NSLog(@"qqq %@",[NSThread currentThread]);
NSLog(@"下载图片");
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"回到主线程");
NSLog(@"%@",[NSThread currentThread]);
}];
}];
推荐阅读
- 慢慢的美丽
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量
- 《跨界歌手》:亲情永远比爱情更有泪点
- 诗歌:|诗歌: 《让我们举起世界杯,干了!》
- 期刊|期刊 | 国内核心期刊之(北大核心)
- 《魔法科高中的劣等生》第26卷(Invasion篇)发售
- 人间词话的智慧
- 《一代诗人》37期,生活,江南j,拨动心潭的一泓秋水
- 广角叙述|广角叙述 展众生群像——试析鲁迅《示众》的展示艺术
- 书评——《小行星》