web-dev-qa-db-ja.com

iOS GCD:グローバルキューとバックグラウンド優先度(DISPATCH_QUEUE_PRIORITY_BACKGROUND)のキューの違いは?

私は Concurrency Programming Guide を読んでおり、物事は私を混乱させます。

バックグラウンドタスクで次のコードを呼び出すコードがたくさんあります。

dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

「背景」とは、一般的な意味です。

メイン(UI)スレッド以外で実行される何か

したがって、ドキュメントに従って、上記のステートメントは、優先順位が異なる非メインスレッドキューを返します。

私の質問は-なぜDISPATCH_QUEUE_PRIORITY_BACKGROUNDが存在するのですか?最近、DISPATCH_QUEUE_PRIORITY_BACKGROUNDを使用してバックグラウンドタスクを実行するための非同期タスクも多く見られます。

DISPATCH_QUEUE_PRIORITY_DEFAULTDISPATCH_QUEUE_PRIORITY_LOW、またはDISPATCH_QUEUE_PRIORITY_HIGHで返されるキューは、dispatch_get_global_queueを使用して返される場合、メインスレッドから非常に離れて実行されませんか?

キューをバックグラウンドにしませんか?キューはDISPATCH_QUEUE_PRIORITY_BACKGROUNDで返される特定の目的は何ですか?私はすでに これを参照 ですが、上で述べた一般的な意味以外はあまり明確ではありません。

バックグラウンドキューとバックグラウンドキューという言葉にかなり混乱していると思います。誰かが(より良い、グラフィカルに)説明できる場合-大きな助けになります。

35
Nirav Bhatt

バックグラウンドタスクが多数ある場合、デバイスのCPUはすべてのタスク間で共有されます。ほとんどの場合、それは正しいことです。タスクの完了に時間がかかりすぎる場合は、より効率的にすることで問題を解決します。

非常にまれなケースでは、時間がかかるタスクがあるかもしれませんが、それはOkで待機します。だから、それに優先度を与えます。NORMALでやるべき仕事がある場合優先度、その作業が最初に行われ、予備のCPUが他に何もしない場合にのみ、バックグラウンドタスクが実行されます。そして、優先度が高いキューがあります;そのキュー内のタスクが最初に実行されます。ある特定のタスクをできるだけ早く終了する必要がある場合他のタスクが遅延することを意味する場合でも

プログラミングロジックの観点から見ると、3つのキューはすべて同一です。 OSが最初に完了しようとするタスクと、それほど気にしないタスクに影響します。

14
gnasher729

これは、dispatch/queue.hヘッダーで非常によく説明されています。

DISPATCH_QUEUE_PRIORITY_HIGHキューにディスパッチされたアイテムは高優先度で実行されます。つまり、デフォルトの優先度または低優先度のキューよりも前に実行されるようにキューがスケジュールされます。

DISPATCH_QUEUE_PRIORITY_DEFAULTキューにディスパッチされたアイテムはデフォルトの優先度で実行されます。つまり、すべての高優先度キューがスケジュールされた後、低優先度キューがスケジュールされる前に、キューの実行がスケジュールされます。

DISPATCH_QUEUE_PRIORITY_LOWキューにディスパッチされたアイテムは低優先度で実行されます。つまり、デフォルトの優先度と高優先度のキューがすべてスケジュールされた後、キューの実行がスケジュールされます。

DISPATCH_QUEUE_PRIORITY_BACKGROUNDキューにディスパッチされたアイテムはバックグラウンド優先度で実行されます。つまり、より高い優先度のキューがすべてスケジュールされた後にキューの実行がスケジュールされ、システムはsetpriority(2)に従ってバックグラウンドステータスのスレッドでこのキューのアイテムを実行します(つまり、ディスクI/Oは調整され、スレッドのスケジューリング優先度は最低値に設定されます。

そして、これはglobalキューであることを覚えておいてください。システムフレームワークのような他のものは、それにスケジューリングされるかもしれません。優先度の高いバンドを飢えさせるのは非常に簡単です-DISPATCH_QUEUE_PRIORITY_HIGHタスクがスケジュールされている場合、デフォルトの優先度のタスクは実行するまでかなり待たなければならない場合があります。また、DISPATCH_QUEUE_PRIORITY_BACKGROUNDのタスクは、very長い時間待機する必要がある場合があります。これらのタスクの上の他の優先順位はすべて空でなければならないためです。

多くの開発者がグローバルな並行キューを悪用しています。ブロックを実行し、キューを必要とし、それをデフォルトの優先度で使用するだけです。そのような実践は、バグのトラブルシューティングが非常に困難になる可能性があります。グローバル同時キューは共有リソースであるため、注意して扱う必要があります。ほとんどの場合、プライベートキューを作成する方が理にかなっています。

並行キューは非同期ではなく、並行です。同期タスクを引き続きスケジュールして、同期タスクを実行できます。シリアルキューのような同時キューは、FIFO順序でデキューします。シリアルキューとは異なり、ブロックを同時に実行します。同時および非同期は同じものではありません。

また、メインスレッドがアイドル状態の場合、並行キューはそのスレッドを再利用できることを覚えておいてください。実際、新しいスレッドを作成するよりも、それを行うことを好みます。同時キューを使用してもguaranteeユーザーインターフェイスはブロックされません。

これらのディスパッチキューに送信されたブロックは、システムによって完全に管理されるスレッドのプールで呼び出されます。どのスレッドでブロックが呼び出されるかについての保証はありません。ただし、FIFOディスパッチキューに送信される1つのブロックのみが一度に呼び出されることが保証されています。

GCDは、並行キューでブロックを実行するために使用されるスレッドについて保証しません。メインキューを使用する場合、ブロックはメインスレッドでシリアルに実行されます。並行キューは任意のスレッドを使用でき、最適化として既存のスレッドを使用することを好みます。再利用できるスレッドがない場合にのみ、新しいスレッドが作成されます。そして実際には、メインスレッドは「ウォーム」であるため、多くの場合、メインスレッドが最初の選択肢です(メインスレッドが作業に使用できる場合)。

繰り返しますが、Grand Central Dispatchを使用すると、メインスレッドでタスクが実行されることを確認できます(メインキューに送信することにより)。メインスレッドでタスクしないを実行することを確認することはできません。

37
quellish