#1:如何使用dispatch source实现一个精准的定时器。
dispatch source是一个监视某些类型事件的对象。当这些事件发生时,它自动将一个block放入一个dispatch queue的执行例程中。
它支持所有kqueue所支持的事件以及mach端口、内建计时器支持(这样我们就不用使用超时参数来创建自己的计时器)和用户事件。
首先定义倒计时接口需要的参数:
TimeCountDown.h
@class TimeCountDown;
@protocol TimeCountDownDelegate <NSObject>
@optional
- (void)timeCountDownPerSecond;
@end
@interface TimeCountDown : NSObject
//Delegate
@property(assign,nonatomic) id<TimeCountDownDelegate> delegate;
//倒计时时间
@property(assign,nonatomic) NSInteger timeInterval;
//开始时间
-(void)startTimer:(NSInteger)timeInterval;
//停止时间
-(void)stopTimer;
@end
TimeCountDown.m中
@interface TimeCountDown(){
dispatch_source_t _processingQueueSource;
}
@property (atomic, assign, getter=isRunning) BOOL running;
@end
@implementation TimeCountDown
-(void)stopTimer{
[self pause];
}
-(void)startTimer:(NSInteger)timeInterval{
_timeInterval=timeInterval;
WEAKSELF
if (_processingQueueSource) {
_processingQueueSource = nil;
}
NSInteger totalTime = self.timeInterval;
_processingQueueSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0,
dispatch_get_main_queue());
dispatch_source_set_event_handler(_processingQueueSource, ^{
if (weakSelf.timeInterval<=0) {
_processingQueueSource = nil;
}else{
weakSelf.timeInterval--;
}
if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(timeCountDownPerSecond)]) {
[weakSelf.delegate timeCountDownPerSecond];
}
});
[self resume];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
for (NSUInteger index = 0; index <totalTime; index++) {
dispatch_source_merge_data(_processingQueueSource, 1);
unsleep(1000000);//1秒
}
});
}
//获取分派源分派处理程序之前恢复
- (void)resume {
if (self.running) return;
self.running = YES;
dispatch_resume(_processingQueueSource);
}
//暂停
- (void)pause {
if (!self.running) return;
self.running = NO;
dispatch_suspend(_processingQueueSource);
}
@end
#2:线程死锁问题:
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"同步线程处理block");
});
}
#死锁原因
#1:dispatch_sync在等待block语句执行完成,而block语句需要在主线程里执行,所以dispatch_sync如果在主线程调用就会造成死锁
#2:dispatch_sync是同步的,本身就会阻塞当前线程,也即主线程。而又往主线程里塞进去一个block,所以就会发生死锁。
#dispatch_async(dispatch_get_global_queue(), ^{
#async 在主线程中 创建了一个异步线程 加入 全局并发队列,async 不会等待 block 执行完成,立即返回
});
}
分析这段代码:view DidLoad 在主线程中,也即dispatch_get_main_queue()中,执行到sync时向dispatch_get_main_queue()插入同步thread,sync会等到后面的block执行完成才返回。sync又在主队列里面,是个串行队列,sync是后面才加入的,前面一个是主线程,所以sync想执行block必须等待前一个主线程执行完成,而主线程却在等待sync返回,去执行后续工作,从而造成死锁。
#2:dispatch_sync 和 dispatch_async 区别:
dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"1");
dispatch_sync(concurrentQueue, ^(){
NSLog(@"2");
[NSThread sleepForTimeInterval:5];
NSLog(@"3");
});
NSLog(@"4");
NSLog(@"11");
dispatch_async(concurrentQueue, ^(){
NSLog(@"21");
[NSThread sleepForTimeInterval:5];
NSLog(@"31");
});
NSLog(@"41");
#dispatch_async(queue,block) async 异步队列,dispatch_async 函数会立即返回, block会在后台异步执行。
#dispatch_sync(queue,block) sync 同步队列,dispatch_sync 函数不会立即返回,即阻塞当前线程,等待 block同步执行完成。
#3 :如何用GCD同步若干个异步调用?
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{ /*加载图片1 */ });
dispatch_group_async(group, queue, ^{ /*加载图片2 */ });
dispatch_group_async(group, queue, ^{ /*加载图片3 */ });
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 合并图片
});
iOS线程问题汇总
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- hello,各位读者,我又回来了啦,感觉上一篇的文章各位的反映还算不错,感谢各位让我有坚持写作的动力。好了,前话就...
- 在日常的 iOS 开发中,关于多线程使用的较多的就是 Grand Central Dispatch(GCD) 了,...