このようなシリアルキューを作成しました。
dispatch_queue_t _serialQueue = dispatch_queue_create("com.example.name", DISPATCH_QUEUE_SERIAL);
dispatch_async
の違いは何ですか?
dispatch_async(_serialQueue, ^{ /* TASK 1 */ });
dispatch_async(_serialQueue, ^{ /* TASK 2 */ });
そして、dispatch_sync
はこのシリアルキューでこのように呼ばれましたか?
dispatch_sync(_serialQueue, ^{ /* TASK 1 */ });
dispatch_sync(_serialQueue, ^{ /* TASK 2 */ });
私の理解では、どのディスパッチ方法が使用されているかにかかわらず、TASK 1
が実行されてからTASK 2
の前に完了します、正しいですか?
はい。シリアルキューを使用すると、タスクのシリアル実行が保証されます。唯一の違いは、dispatch_sync
はブロックが終了した後にのみ戻るのに対して、dispatch_async
はキューに追加された後に戻り、終了しない場合があることです。
このコードの
dispatch_async(_serialQueue, ^{ printf("1"); });
printf("2");
dispatch_async(_serialQueue, ^{ printf("3"); });
printf("4");
2413
または2143
または1234
を印刷できますが、1
は常に3
の前に印刷されます。
このコードの
dispatch_sync(_serialQueue, ^{ printf("1"); });
printf("2");
dispatch_sync(_serialQueue, ^{ printf("3"); });
printf("4");
常に1234
を出力します
注:最初のコードについては、ない print 1324
。 printf("3")
がディスパッチされるためafterprintf("2")
が実行されます。また、タスクは実行できますafterディスパッチされます。
タスクの実行時間は何も変わりません。このコードは常に12
を出力します
dispatch_async(_serialQueue, ^{ sleep(1000);printf("1"); });
dispatch_async(_serialQueue, ^{ printf("2"); });
何が起こったのかも
常に12
が表示されます
dispatch_sync
とdispatch_async
の違いは簡単です。
どちらの例でも、TASK 1
は常にTASK 2
の前に実行されます。これは、前にディスパッチされたためです。
ただし、dispatch_sync
の例では、TASK 2
がディスパッチおよび実行されるまで、TASK 1
をディスパッチしません。これは "blocking" と呼ばれます。コードは、タスクが実行されるまで待機(または「ブロック」)します。
dispatch_async
の例では、コードは実行が完了するまで待機しません。両方のブロックがキューにディスパッチ(およびエンキュー)され、残りのコードはそのスレッドで実行を継続します。その後、将来のある時点で(キューにディスパッチされたものに応じて)、Task 1
が実行され、次にTask 2
が実行されます。
それはすべてメインキューに関連しています。 4つの順列があります。
i)シリアルキュー、非同期ディスパッチ:ここでタスクは次々に実行されますが、メインスレッド(UIへの影響)は戻りを待機しません
ii)シリアルキュー、ディスパッチ同期:ここでタスクは次々に実行されますが、メインスレッド(UIへの影響)に遅れが表示されます
iii)同時キュー、非同期ディスパッチ:ここで、タスクは並行して実行され、メインスレッド(UIへの影響)は戻りを待たずにスムーズになります。
iv)同時キュー、ディスパッチ同期:ここでは、タスクは並行して実行されますが、メインスレッド(UIへの影響)に遅延が表示されます
同時キューまたはシリアルキューの選択は、次のタスクの前のタスクからの出力が必要かどうかによって異なります。前のタスクに依存している場合は、シリアルキューを採用するか、並行キューを使用します。
そして最後に、これはビジネスを終えたときにメインスレッドに戻る方法です:
DispatchQueue.main.async {
// Do something here
}