*

iOS(Xcode6とObjective-C)におけるマルチスレッド(非同期)処理の実装方法その2[GCD(Grand Central Dispatch)の利用]

公開日: : 最終更新日:2014/11/16 Objective-C ,


スポンサードリンク



本エントリーではGCD(Grand Central Dispatch)を利用したiOSのマルチスレッド(非同期)処理の実装方法を説明させていただきます。
GCDはiOS4.0以降で利用可能です。

利用しているXcodeは6.1です。
エントリーの内容は以下の通りです。

  1. GCD(Grand Central Dispatch)の概要
  2. シリアルキューとコンカレントキューを利用したマルチスレッド処理
  3. メインディスパッチキューを利用したマルチスレッド処理
  4. 各種キューを組み合わせたマルチスレッド処理

1 GCD(Grand Central Dispatch)の概要

GCDで利用できるキュー

GCDで利用できるキューの種類は以下の3つとなります。

  • シリアルキュー(Serial Queue)
  • コンカレントキュー(Concurrent Queue)
  • メインディスパッチキュー(Main Dispatch Queue)

全てのキューにはブロックを追加することができます。
ブロックの詳細は「Xcode6&Objective-Cにおけるブロック構文(Blocks記法)の利用方法」をご覧ください。

キューにブロックを追加することで、ブロックで定義されている処理をワーカースレッド(メインディスパッチキューはメインスレッド)が実行してくれます。

各キューの動作のイメージと概説

シリアルキュー(Serial Queue)

シリアルキューは、dispatch_queue_create()関数に名前を指定して作成します。この名前を指定して作成したキューに対してブロックを追加することでワーカースレッドがブロックを処理するのですが、シリアルキューでは同時実行されるブロックは単一です。
スクリーンショット 2014-11-14 22.12.56

コンカレントディスパッチキュー(Concurrent Dispatch Queue)

コンカレントディスパッチキューは、dispatch_get_global_queue()関数を利用することで取得できます。取得したキューに対してブロックを追加することでワー複数のワーカースレッドがブロックをキューから取り出して実行します。
当然ですが、同時実行されるスレッドの上限はワーカースレッド数となります。
(ワーカースレッドの数はコア数に応じて自動的に決定されます。)
スクリーンショット 2014-11-14 22.31.42

メインディスパッチキュー(Main Dispatch Queue)

iOSアプリケーションでは、利用者が何も操作しなくてもメインスレッドはRun Loopとして常に動作しています。メインディスパッチキューを利用すればメインスレッドに処理を実行させることが簡単にできます。メインディスパッチキューが利用できないバージョンのiOSではNSObjectクラスの performSelectorOnMainThread:withObject:waitUntilDone:メソッドを利用する必要がありまましたが、メインディスパッチキューが利用できるようになって格段に処理が簡単になりました。

UIコンポーネント(iOSアプリケーションで画面に表示しているラベルやテキストボックス等)の表示テキスト等を変更する処理は、メインスレッドで行う必要がありますのでメインディスパッチキューの存在意義は大きいといえます。

実際の動作イメージとしては、シリアルキューのワーカースレッドに対応する部分がメインスレッドになっており、当然メインスレッドですのでキューに追加された処理だけをワーカースレッドは処理しておらず、他の処理の片手間でおこなっている感じとなります。
スクリーンショット 2014-11-15 16.20.34

2 シリアルキューとコンカレントキューを利用したマルチスレッド処理

シリアルキューを利用したスレッド処理

シリアルキューの利用方法

シリアルキューはdispatch_queue_create関数にキューの名前を指定する文字列とNULLを引数として呼び出すことで作成可能です。

キューの追加はdispath_async関数にキューとブロックを指定して呼び出すことで行えます。

シリアルキューの利用例

キューに追加するブロックの処理なNSLogとスリープ処理のみの簡単な利用例は以下の通りです。

実行したときのログは以下のようになりました。

シリアルキューなので、ワーカースレッドが1つしか存在していないことが各行のスレッド番号が同じことから確認できます。
シリアルキューを利用する場合は全ての処理がスレッドセーフとなりますので共有リソースの保護に気を配る必要はありません。

コンカレントキューを利用したスレッド処理

コンカレントキューの利用方法

コンカレントキューを利用する方法は2種類存在しています。
1つ目は、dispatch_queue_create関数にキューの名前を指定する文字列とDISPATCH_QUEUE_CONCURRENTを引数として呼び出し作成する方法
2つ目は、dispatch_get_global_queue関数に優先度と0(今後の拡張用のための引数)を指定して呼び出すことでで既存のキューを取得する方法
優先度には以下の値が指定可能です。

  • DISPATCH_QUEUE_PRIORITY_HIGH(優先度高)
  • DISPATCH_QUEUE_PRIORITY_DEFAULT(優先度中)
  • DISPATCH_QUEUE_PRIORITY_LOW(優先度低)
  • DISPATCH_QUEUE_PRIORITY_BACKGROUND(バックグラウンド)

当然ですが、既存のキューを利用する方が消費リソース面等で有利であると言えます.

1つ目の方法の例

2つめの方法の例

キューの追加の仕方はシリアルキューと同じでdispath_async関数にキューとブロックを指定して呼び出すことで行えます。

コンカレントキューの利用例

コンカレントキューは>DISPATCH_QUEUE_PRIORITY_HIGH(優先度高)を指定してdispatch_get_global_queue関数で既存のキューを取得する方法を利用しました。

他の部分は全てシリアルキューの利用例と同じとしています。

実行したときのログは以下のようになりました。

このログからワーカースレッドは5個以上あることが分かります。
またキューに登録されたブロックは、FIFO(First In, First Out)で処理されていることも分かります。
各ブロックの内部処理でスリープ時間がランダムに決定されるので、処理が終わる順番もランダムになっています。今回はわざと処理にかかる時間をずらしましたが、同様のことが実際の実装でも起こると言え、共有リソースの保護(スレッドセーフプログラミング)に留意(@synchronized等の利用)する必要があります。

3 メインディスパッチキューを利用したマルチスレッド処理

メインディスパッチキューの利用方法

dispatch_get_main_queue関数を呼び出して、既に存在しているメインディスパッチキューを取得します。

メインディスパッチキューの利用例

コンカレントキューの利用例を3カ所変更するだけになります。
1つ目の変更点は、main関数内でNSLogでログを出力する処理の追加
2つ目の変更点は、キューの取得部分となります。
3つ目はmain関数内の最後のsleep(100)です。これではメインスレッドは100秒休んでしまいますので、分散してsleepしてもらいます。

main関数内でNSLogでログを出力することにより、メインディスパッチキューに追加された処理がメインスレッドで動作しているかを確認したいとの意図です。
変更後のコードは以下のようになりました。

実行してみると、main start出力されるだけで全然思ったように動作してくれません・・・
for文が回るタイミングでコンカレントキューに追加されたキューを処理してくれると思ったのですが・・・

やはり本当のRun Loopが存在しないとうまく動作しないようです。
メインディスパッチキューの利用例についてはSwift編でiOSアプリケーションを例として動作検証を行わせていただきます。

4 各種キューを組み合わせたマルチスレッド処理

各種キューを組み合わせたマルチスレッド処理のサンプルとその説明をと思ったのですが、この例はSwiftのエントリーで記載させていただきます。


スポンサードリンク

Googleアドセンス

Googleアドセンス




関連記事

Xcode5のEmpty Application templateでStoryboardを利用する。

Xcode5のEmpty Application templateでStoryboardを利用する方

記事を読む

Xcode5でUnitTest(XCTestフレームワーク)を利用してみる。

Xcode5(iOS7対応バージョンの統合開発)を利用するので、当然言語はObjective-Cです

記事を読む

Xcode5でInterface Builderの接続状態の確認と切断を行う。

「Xcode5で画面コンポーネントを利用するための基本」で本来説明すべき内容でしたが あちらのエン

記事を読む

Xcode5を軽快に利用するためのショートカット[基本編]

「Xcode5のエディタエリアの説明 」 「Xcode5のエディタエリアの説明 [中編]」 「X

記事を読む

Xcode5でイメージ(画像)を表示&操作する[前編]

Xcodeでアプリ開発を行う時に、イメージ(画像)の表示は必須な処理であると言えます。 前回のエン

記事を読む

Xcode5でSchemeを利用する。[後編]

「Xcode5でSchemeを利用する。」の続きの「Xcode5でSchemeを利用する。[後編]」

記事を読む

Xcode5&Objective-Cでセグエを利用して画面遷移を実現する。[前編:モックの作成]

iPhoneアプリの画面遷移と言えば、真っ先に挙がるのが「ナビゲーションコントローラ」なのですが

記事を読む

Xcodeのユーティリティエリアの使い方[ソースファイル表示時]

本エントリーでは、Xcodeの「ユーティリティエリア」の使い方を説明させていただきます。 利用

記事を読む

Xcode5で画面コンポーネント(UIコンポーネント)配置して利用するための基本

iOSアプリケーションは当然ですが、画面がありますよね。 言わずもがなですが、iOS向けのアプ

記事を読む

Xcodeの使い方

Objective-Cでコーディングを行うための統合開発環境のXcodeの利用方法のエントリーです。

記事を読む

Comment

  1. […] 続きはリンク先にて iOS(Xcode6とObjective-C)におけるマルチスレッド(非同期)処理の実装方法その2[GCD(Grand Central Dispatch)の利用] […]

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

動画で英語を学習できるiOSの無料アプリCapTubeをリリースいたしました。

個人では初となるiOSアプリをリリースいたしました。 何度もリジ

no image
Ruby on rails4系でBootstrapを利用するためのtips

MacでRuby on rails4系のBootstrapを利用しよう

no image
Java、Eclipse、JUnit関連のエントリーの移行のお知らせ

Java、Eclipse、JUnit関連のエントリーは http:/

iOS8開発者向けお勧め本紹介[詳細! Swift iPhoneアプリ開発 入門ノート Swift 1.1+Xcode 6.1+iOS 8.1対応]

iOS7開発者向けお勧め本紹介を以前に紹介させていただきまいたが、今回

Swift入門(Xcode6のXCTestフレームワークで学ぶ) 第二回「関数(メソッド)とクロージャーの利用方法」

前回はSwiftの概要をザックリと説明させていただきました。 今

→もっと見る

Optimization WordPress Plugins & Solutions by W3 EDGE
PAGE TOP ↑