iOS多線程中performSelector: 和dispatch_time的不一樣

iOS中timer相關的延時調用,常見的有NSObject中的performSelector:withObject:afterDelay:這個方法在調用的時候會設置當前runloop中timer,還有一種延時,直接使用NSTimer來配置任務。java

這兩種方式都一個共同的前提,就是當前線程裏面須要有一個運行的runloop而且這個runloop裏面有一個timer。安全

咱們知道:只有主線程會在建立的時候默認自動運行一個runloop,而且有timer,普通的子線程是沒有這些的。這樣就帶來一個問題了,有些時候咱們並不肯定咱們的模塊是否是會異步調用到,而咱們在寫這樣的延時調用的時候通常都不會去檢查運行時的環境,這樣在子線程中被調用的時候,咱們的代碼中的延時調用的代碼就會一直等待timer的調度,可是實際上在子線程中又沒有這樣的timer,這樣咱們的代碼就永遠不會被調到。多線程

下面的代碼展現了performSelector和dispatch_time的不一樣併發

/*
 testDispatch_after 延時添加到隊列
 */
-(void) testDispatch_after{
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3*NSEC_PER_SEC);
    dispatch_after(time, dispatch_get_main_queue(), ^{
        NSLog(@"3秒後添加到隊列");
    });
}
-(void) testDelay{
    NSLog(@"3秒後testDelay被執行");
}
/*
 dispatch_barrier_async 柵欄的做用
 */
-(void) testDispatch_Barrier{
    //dispatch_queue_t gcd = dispatch_queue_create("這是序列隊列", NULL);
    dispatch_queue_t gcd = dispatch_queue_create("這是併發隊列", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(gcd, ^{
        NSLog(@"b0");
        //這個selector不會執行
        [self performSelector:@selector(testDelay) withObject:nil afterDelay:3];
        //代碼會執行
        //[self testDispatch_after];
    });
    dispatch_release(gcd);
}
在有多線程操做的環境中, 這樣performSelector的延時調用,實際上是缺少安全性的。咱們能夠用另外一套方案來解決這個問題,就是使用GCD中的dispatch_after來實現單次的延時調用
相關文章
相關標籤/搜索