web-dev-qa-db-ja.com

dispatch_get_global_queueとdispatch_queue_createの違いは何ですか?

ある程度の長い操作(解析、ネットワークへの接続など)のために複数のスレッドを必要とする、やや複雑なiOSプログラムを書いています。ただし、dispatch_get_global_queuedispatch_queue_createの違いについては混乱しています。

どちらを使用する必要がありますか?一般的な違いは何ですか?ありがとう。

42
Nosrettap

documentation で説明されているように、グローバルキューは並行タスクに適しています(つまり、さまざまなタスクを非同期にディスパッチし、並行して実行すれば完全に満足します)。独自のキューを作成および破棄する理論上のオーバーヘッドに遭遇します。

独自のキューの作成は、シリアルキューが必要な場合(つまり、ディスパッチされたブロックを1つずつ実行する必要がある場合)に非常に役立ちます。これは、各タスクが前のタスクに依存している場合や、複数のスレッドからの共有リソースとの相互作用を調整する場合など、多くのシナリオで役立ちます。

あまり一般的ではありませんが、 barriers を並行キューと組み合わせて使用​​する必要がある場合は、独自のキューを作成することもできます。そのシナリオでは、並行キューを作成します(つまり、dispatch_queue_create とともに DISPATCH_QUEUE_CONCURRENTオプション)、そのキューと一緒にバリアを使用します。グローバルキューでバリアを使用しないでください。

私の一般的な助言は、シリアルキューが必要な場合(またはバリアを使用する必要がある場合)、キューを作成することです。そうでない場合は、グローバルキューを使用して、独自のキューを作成するオーバーヘッドを回避してください。


同時キューが必要であるが、同時に実行できる操作の数を制御する場合は、NSOperationQueueプロパティを持つ maxConcurrentOperationCount の使用を検討することもできます。これは、ネットワーク操作を行うときに役立ち、サーバーに送信される同時要求が多すぎないようにする必要があります。

71
Rob

別の回答で投稿しましたが、ここにかなり前に書いたものがあります:

キューを概念化する最良の方法は、最初に、非常に低レベルでは、シリアルと同時の2種類のキューしかないことを認識することです。

シリアルキューは一夫一婦ですが、コミットされていません。一連のタスクを各シリアルキューに渡すと、一度に1つのスレッドのみを使用して、タスクを一度に1つずつ実行します。コミットされていない側面は、シリアルキューが異なるスレッドbetweenタスクに切り替えられる可能性があることです。シリアルキューは、タスクが完了するのを常に待ってから次のタスクに進みます。したがって、タスクはFIFOの順序で完了します。dispatch_queue_createを使用すると、必要な数のシリアルキューを作成できます。

メインキューは特別なシリアルキューです。コミットされていない他のシリアルキューとは異なり、多くのスレッドを「デート」しますが、メインスレッドはメインスレッドと「結婚」し、すべてのタスクが実行されます。メインキューのジョブは、小さな操作がUIやその他の重要な部分をブロックしないように、runloopで適切に動作する必要があります。すべてのシリアルキューと同様に、タスクはFIFOの順序で完了します。

シリアルキューが一夫一婦の場合、同時キューは無差別です。システムの負荷に応じて、利用可能なスレッドにタスクを送信したり、新しいスレッドを作成したりします。異なるスレッドで複数のタスクを同時に実行できます。グローバルキューに送信されるタスクはスレッドセーフであり、副作用を最小限に抑えることが重要です。タスクは、実行のためにFIFOの順序で送信されますが、完了の順序は保証されていません。 dispatch_get_global_queueで。

編集:この答えを拡張したブログ投稿: http://amattn.com/p/grand_central_dispatch_gcd_summary_syntax_best_practices.html

40
amattn

1つは既存のグローバルキューを返し、もう1つは新しいキューを作成します。 GCDを使用する代わりに、NSOperationと操作キューの使用を検討します。詳細については、このガイドで見つけることができます 通常、操作を同時に実行したい場合は、独自のキューを作成して、その中の操作。

0
Max Yankov