#1:如何使用dispatch source實(shí)現(xiàn)一個(gè)精準(zhǔn)的定時(shí)器。
dispatch source是一個(gè)監(jiān)視某些類(lèi)型事件的對(duì)象。當(dāng)這些事件發(fā)生時(shí),它自動(dòng)將一個(gè)block放入一個(gè)dispatch queue的執(zhí)行例程中。
它支持所有kqueue所支持的事件以及mach端口、內(nèi)建計(jì)時(shí)器支持(這樣我們就不用使用超時(shí)參數(shù)來(lái)創(chuàng)建自己的計(jì)時(shí)器)和用戶事件。
首先定義倒計(jì)時(shí)接口需要的參數(shù):
TimeCountDown.h
@class TimeCountDown;
@protocol TimeCountDownDelegate <NSObject>
@optional
- (void)timeCountDownPerSecond;
@end
@interface TimeCountDown : NSObject
//Delegate
@property(assign,nonatomic) id<TimeCountDownDelegate> delegate;
//倒計(jì)時(shí)時(shí)間
@property(assign,nonatomic) NSInteger timeInterval;
//開(kāi)始時(shí)間
-(void)startTimer:(NSInteger)timeInterval;
//停止時(shí)間
-(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秒
}
});
}
//獲取分派源分派處理程序之前恢復(fù)
- (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:線程死鎖問(wèn)題:
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"同步線程處理block");
});
}
#死鎖原因
#1:dispatch_sync在等待block語(yǔ)句執(zhí)行完成,而block語(yǔ)句需要在主線程里執(zhí)行,所以dispatch_sync如果在主線程調(diào)用就會(huì)造成死鎖
#2:dispatch_sync是同步的,本身就會(huì)阻塞當(dāng)前線程,也即主線程。而又往主線程里塞進(jìn)去一個(gè)block,所以就會(huì)發(fā)生死鎖。
#dispatch_async(dispatch_get_global_queue(), ^{
#async 在主線程中 創(chuàng)建了一個(gè)異步線程 加入 全局并發(fā)隊(duì)列,async 不會(huì)等待 block 執(zhí)行完成,立即返回
});
}
分析這段代碼:view DidLoad 在主線程中,也即dispatch_get_main_queue()中,執(zhí)行到sync時(shí)向dispatch_get_main_queue()插入同步thread,sync會(huì)等到后面的block執(zhí)行完成才返回。sync又在主隊(duì)列里面,是個(gè)串行隊(duì)列,sync是后面才加入的,前面一個(gè)是主線程,所以sync想執(zhí)行block必須等待前一個(gè)主線程執(zhí)行完成,而主線程卻在等待sync返回,去執(zhí)行后續(xù)工作,從而造成死鎖。
#2:dispatch_sync 和 dispatch_async 區(qū)別:
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 異步隊(duì)列,dispatch_async 函數(shù)會(huì)立即返回, block會(huì)在后臺(tái)異步執(zhí)行。
#dispatch_sync(queue,block) sync 同步隊(duì)列,dispatch_sync 函數(shù)不會(huì)立即返回,即阻塞當(dāng)前線程,等待 block同步執(zhí)行完成。
#3 :如何用GCD同步若干個(gè)異步調(diào)用?
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線程問(wèn)題匯總
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
相關(guān)閱讀更多精彩內(nèi)容
- hello,各位讀者,我又回來(lái)了啦,感覺(jué)上一篇的文章各位的反映還算不錯(cuò),感謝各位讓我有堅(jiān)持寫(xiě)作的動(dòng)力。好了,前話就...
- 在日常的 iOS 開(kāi)發(fā)中,關(guān)于多線程使用的較多的就是 Grand Central Dispatch(GCD) 了,...
- 每每我進(jìn)行自我介紹時(shí)都喜歡說(shuō)自己是一個(gè)愛(ài)讀書(shū)的人,說(shuō)自己愛(ài)閱讀,喜靜?,F(xiàn)在我才發(fā)現(xiàn)我真的不算是一個(gè)很愛(ài)讀書(shū)的人,因...
- 1. 應(yīng)該是很多年前,SHE組合的三個(gè)人還在一起的時(shí)候,她們一塊兒演了部電影,是賀歲片,我忘了叫什么名字了,印象深...