5

der Testcode wie folgt:Abfertigungsrichtlinie der gleichzeitigen Verwendung von GCD-Warteschlange, wenn der Schlaf in einem Thread

dispatch_queue_t queue = dispatch_queue_create("sc", DISPATCH_QUEUE_CONCURRENT); 

dispatch_async(queue, ^{ 
    [NSThread sleepForTimeInterval:10]; 
    NSLog(@"10s --- %@", [NSThread currentThread]); 
}); 

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), queue, ^{ 
    NSLog(@"First: 5s --- %@", [NSThread currentThread]); 
}); 

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), queue, ^{ 
    NSLog(@"Second: 5s --- %@", [NSThread currentThread]); 
}); 

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), queue, ^{ 
    NSLog(@"Third: 5s --- %@", [NSThread currentThread]); 
}); 

Hier habe ich eine gleichzeitige Warteschlange und schlafen async Weise ein Faden verwendet wird.

jedoch der Ausgang ist:

2016-03-26 12:17:57.164 TestPlayground[28188:551287] 10s --- <NSThread: 0x7fa080511730>{number = 2, name = (null)} 
2016-03-26 12:17:57.165 TestPlayground[28188:551287] First: 5s --- <NSThread: 0x7fa080511730>{number = 2, name = (null)} 
2016-03-26 12:17:57.166 TestPlayground[28188:551307] Second: 5s --- <NSThread: 0x7fa080704a80>{number = 3, name = (null)} 
2016-03-26 12:17:57.166 TestPlayground[28188:551301] Third: 5s --- <NSThread: 0x7fa080511530>{number = 4, name = (null)} 

Es scheint, dass GCD Block ersten Thread für 10 Sekunden und dann starten Sie es neuen Thread für die gleichzeitige Arbeiten zu schaffen.

Aber wenn ich ersetzen Sie einfach die selbst erstellte Warteschlange mit den globalen gleichzeitigen Warteschlange und ändern Sie nicht die folgenden Job

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
// ... same as before 

Der Ausgang ist vernünftiger

2016-03-26 12:23:29.496 TestPlayground[28320:558467] First: 5s --- <NSThread: 0x7ff473c08b80>{number = 4, name = (null)} 
2016-03-26 12:23:29.496 TestPlayground[28320:558483] Second: 5s --- <NSThread: 0x7ff473f18c50>{number = 2, name = (null)} 
2016-03-26 12:23:29.496 TestPlayground[28320:558471] Third: 5s --- <NSThread: 0x7ff473d0a7c0>{number = 3, name = (null)} 
2016-03-26 12:23:34.030 TestPlayground[28320:558456] 10s --- <NSThread: 0x7ff473e218e0>{number = 5, name = (null)} 

Was ist der Versand Regel in GCD für diese Art von Jobs? Und warum unterscheiden sich die selbst erstellten konkurrierenden Queues mit der globalen Queue?


Wenn ich einen neuen Job vor dem Schlaf Job hinzufügen

dispatch_queue_t queue = dispatch_queue_create("sc", DISPATCH_QUEUE_CONCURRENT); 

dispatch_async(queue, ^{ NSLog(@"start --- %@", [NSThread currentThread]); }); 

dispatch_async(queue, ^{ 
    [NSThread sleepForTimeInterval:10]; 
    NSLog(@"10s --- %@", [NSThread currentThread]); 
}); 
// ... same as before 

Der Ausgang ist

2016-03-26 12:44:25.728 TestPlayground[28616:571502] start --- <NSThread: 0x7fb7c1604250>{number = 2, name = (null)} 
2016-03-26 12:44:35.733 TestPlayground[28616:571511] 10s --- <NSThread: 0x7fb7c1422e40>{number = 3, name = (null)} 
2016-03-26 12:44:35.734 TestPlayground[28616:571517] First: 5s --- <NSThread: 0x7fb7c16032d0>{number = 4, name = (null)} 
2016-03-26 12:44:35.734 TestPlayground[28616:571511] Second: 5s --- <NSThread: 0x7fb7c1422e40>{number = 3, name = (null)} 
2016-03-26 12:44:35.734 TestPlayground[28616:571552] Third: 5s --- <NSThread: 0x7fb7c1608950>{number = 5, name = (null)} 
+0

Als Test nennen 'dispatch_async (Queue,^{NSLog (@ "beginnen ---% @", [NSThread current]);});' vor dem Aufruf von ' dispatch_async ", die den Schlaf enthält. Welchen Einfluss hatte das? – rmaddy

+0

@rmaddy Ich habe den Beitrag mit Ausgabe aktualisiert. Es scheint, dass es nur einen neuen Thread für den Job verwendet. –

+0

@ xi.lin Ja - das ist bizarr. Ich werde das Dispatch-Team nach diesem Verhalten fragen und, wenn ich die Chance bekomme, die Quelle ziehen und es selbst debuggen, da ich ziemlich neugierig bin. – bbum

Antwort

3

die Ausgabe des folgenden vor:

00:53:38.852 asdfasdfasdf[11650:2114104] start 
00:53:38.854 asdfasdfasdf[11650:2114104] main <NSThread: 0x100206110>{number = 1, name = main} 
00:53:38.854 asdfasdfasdf[11650:2114126] Enter sleep block 
00:53:38.854 asdfasdfasdf[11650:2114127] bare async 
00:53:48.858 asdfasdfasdf[11650:2114126] Sleep block done (10 seconds). 
00:53:48.859 asdfasdfasdf[11650:2114126] dispatch_after() 5 --- <NSThread: 0x10020aa00>{number = 2, name = (null)} 

Also, die schlafender Thread blockiert den Aufruf von as nicht Inkrementelle Blöcke (auch wenn ein Thread-Sleep ausgelöst wurde), blockieren jedoch die Ausführung von dispatch_after().

Was mich verwirrt. rdar: // 25373048

dispatch_queue_t queue = dispatch_queue_create("sc", DISPATCH_QUEUE_CONCURRENT); 

    NSLog(@"start"); 
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
     NSLog(@"main %@", [NSThread currentThread]); 

     dispatch_async(queue, ^{ 
      NSLog(@"Enter sleep block"); 
      [NSThread sleepForTimeInterval:10]; 
      NSLog(@"Sleep block done (10 seconds)."); 
     }); 

     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), queue, ^{ 
      NSLog(@"dispatch_after() 5 --- %@", [NSThread currentThread]); 
     }); 

     dispatch_async(queue, ^{ 
      NSLog(@"bare async"); 
     }); 
    }); 

    [[NSRunLoop currentRunLoop] run]; 
+0

Ja, es scheint, dass "dispatch_after" sich von "dispatch_async" unterscheidet. Und es scheint, dass die globale gleichzeitige Warteschlange einige spezielle Strategien hat. –

+0

@ xi.lin es ist ein Bug im Versand, der in einer zukünftigen Version behoben wird (keine Ahnung wann). Im Moment empfehle ich die Verwendung von dispatch_after für die globale Warteschlange und dann dispatch_async für Ihre Zielwarteschlange, wenn Sie dieses Muster wirklich benötigen. – bbum

+0

Ihr Radar wird jetzt vom Entwicklerteam bestätigt? Danke für die Information. Letzte Nacht habe ich versucht, den Quellcode von libdispatch zu lesen, aber ich habe den Grund noch nicht gefunden. –