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來實現單次的延時調用