ゆるい感じのプログラムを書きたい。

プログラムの敷居を下げて、多くの人が開発出来るように色々書いていきます!

【iPhoneアプリ】他にもまだまだあった「マルチスレッド」について dispatch_group_xxxxxx編

今回は、「マルチスレッド dispatch_group_xxxxx編」についてです。

2部構成の2部目「dispatch_group_xxxxx編」について記載します。
今回は、1ページで収まっております。

dispatch_groupについて

・「dispatch_group」は、いくつかの処理を分散処理させ、結果をまとめて処理を
 行いたい時に利用します。

また、「dispatch_group」には、下記のような種類のメソッドを利用できます。


■dispatch_group_create
・ブロックオブジェクトを関連させる事が可能な新しいグループを作成します。

引数 説明
void 引数指定無し


■dispatch_group_async
・引数で記述したブロック構文の処理を行う、指定したキューオブジェクトに
 グループの関連付けを行う

引数 説明
dispatch_group_t ディスパチグループオブジェクト
dispatch_queue_t ディスパチキューオブジェクト
dispatch_block_t タスク処理が書かれたblock構文


■dispatch_group_async_f
・引数で指定した関数の処理を行う、指定されたキューオブジェクトにグループ
 の関連付けを行う。

引数 説明
dispatch_group_t ディスパチグループオブジェクト
dispatch_queue_t ディスパチキューオブジェクト
void * 関数の引数:汎用ポインタ
dispactch_function 関数名


■dispatch_group_enter
・グループの関連付けを開始する。
(本当はもっと内容は複雑ですが、簡単に理解する為このように記載します。)

引数 説明
dispatch_group_t ディスパチグループオブジェクト


■dispatch_group_leave
・グループの関連付けを終了する。
(本当はもっと内容は複雑ですが、簡単に理解する為このように記載します。)

引数 説明
dispatch_group_t ディスパチグループオブジェクト


■dispatch_group_notify
・グループ内のブロック処理が完了後、記載されたblock構文の処理を行う
 「dispatch_group_wait」は待たなく、次の処理へ進む。

引数 説明
dispatch_group_t ディスパチグループオブジェクト
dispatch_queue_t ディスパチキューオブジェクト
dispatch_block_t タスク処理が書かれたblock構文


■dispatch_group_notify_f
・グループ内のブロック処理が完了後、記載された関数の処理を行う
 「dispatch_group_wait」は待たなく、次の処理へ進む。

引数 説明
dispatch_group_t ディスパチグループオブジェクト
dispatch_queue_t ディスパチキューオブジェクト
void * 関数の引数:汎用ポインタ
dispactch_function 関数名


■dispatch_group_wait
・グループ内の全てのブロック処理を待つ。

引数 説明
dispatch_group_t ディスパチグループオブジェクト
timeout 待ち時間をdispatch_time_t 型(unit64_t型)を使ってナノ秒単位で指定


「dispatch_group_async」を用いたグループ処理


・プログラムはこんな感じに書きます。

- (IBAction)thread_Button:(UIButton*)sender
{

   //グローバルキューの作成
   dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
   //DispatchGroup の生成
   dispatch_group_t group = dispatch_group_create();
   
   /*
    * グループ処理1 
    */
   for (NSInteger i = 0 ; i < 5; ++i) {
     dispatch_group_async(group,queue, ^{
       NSLog(@"グループ_処理1_実行回数:%d %p", i,[NSThread currentThread]);
     });
   }

   /*
    * グループ処理2 
    */
   for (NSInteger i = 0 ; i < 5; ++i) {
     dispatch_group_async(group,con_queue, ^{
       NSLog(@"グループ_処理2_実行回数:%d %p",i,[NSThread currentThread]);
     });
   }

   //グループのblock処理終了まで待機
   dispatch_group_wait(group,DISPATCH_TIME_FOREVER);
   NSLog(@"同期処理:%p",[NSThread currentThread]);
}


・結果はこんな感じです。

labo[23106:3707] グループ_処理1_実行回数:1 0x17595ea0
labo[23106:1803] グループ_処理1_実行回数:0 0x17668590
labo[23106:1803] グループ_処理1_実行回数:2 0x17668590
labo[23106:1803] グループ_処理1_実行回数:3 0x17668590
labo[23106:1803] グループ_処理2_実行回数:0 0x17668590
labo[23106:3707] グループ_処理1_実行回数:4 0x17595ea0
labo[23106:1803] グループ_処理2_実行回数:1 0x17668590
labo[23106:3707] グループ_処理2_実行回数:2 0x17595ea0
labo[23106:1803] グループ_処理2_実行回数:3 0x17668590
labo[23106:3707] グループ_処理2_実行回数:4 0x17595ea0
labo[23106:60b] 同期処理:0x17559a80

この処理では、2つの「dispatch_group_async」が実行された後、「同期処理」が実行されている事が分かります。


「dispatch_group_enter」「dispatch_group_leave」を用いたグループ処理


・プログラムはこんな感じに書きます。

- (IBAction)thread_Button:(UIButton*)sender
{

   //グローバルキューの作成
   dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
   //DispatchGroup の生成
   dispatch_group_t group = dispatch_group_create();

   /*
    * グループ処理1 
    */
   for (NSInteger i = 0 ; i < 5; ++i) {
      //グループの関連付けを開始する。
      dispatch_group_enter(group);
      //「dispatch_group_async」ではない非同期処理を実施	
      dispatch_async(queue, ^{
         NSLog(@"グループ_処理1_実行回数:%d %p", i,[NSThread currentThread]);
         //グループの関連付けを終了する。
         dispatch_group_leave(group);
         //ここはグループ化されてないので待ってない。
         NSLog(@"グループ外_処理1_実行回数:%d %p", i,[NSThread currentThread]);
      });
   }

   //グループのblock処理終了まで待機
   dispatch_group_wait(group,DISPATCH_TIME_FOREVER);
   NSLog(@"同期処理:%p",[NSThread currentThread]);
}


・結果はこんな感じです。

labo[23715:1803] グループ_処理1_実行回数:0 0x14625cf0
labo[23715:3707] グループ_処理1_実行回数:1 0x145526c0
labo[23715:1803] グループ外_処理1_実行回数:0 0x14625cf0
labo[23715:1803] グループ_処理1_実行回数:2 0x14625cf0
labo[23715:3707] グループ外_処理1_実行回数:1 0x145526c0
labo[23715:1803] グループ外_処理1_実行回数:2 0x14625cf0
labo[23715:3707] グループ_処理1_実行回数:3 0x145526c0
labo[23715:1803] グループ_処理1_実行回数:4 0x14625cf0
labo[23715:3707] グループ外_処理1_実行回数:3 0x145526c0
labo[23715:60b]  同期処理:0x14518150
labo[23715:1803] グループ外_処理1_実行回数:4 0x14625cf0

この処理では、グループの関連づけされていない「グループ外_処理1」の処理を待たずに「同期処理」が実行されている事が分かります。


・イメージはこんな感じです。

f:id:kassans:20140331192650p:plain


「dispatch_group_notify」を用いたグループ処理


・プログラムはこんな感じに書きます。

- (IBAction)thread_Button:(UIButton*)sender
{

   //グローバルキューの作成
   dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
   //DispatchGroup の生成
   dispatch_group_t group = dispatch_group_create();

   /*
    * グループ処理1 
    */
   for (NSInteger i = 0 ; i < 5; ++i) {
      //グループの関連付けを開始する。
      dispatch_group_enter(group);
      //「dispatch_group_async」ではない非同期処理を実施	
      dispatch_async(queue, ^{
         NSLog(@"グループ_処理1_実行回数:%d %p", i,[NSThread currentThread]);
         //グループの関連付けを終了する。
         dispatch_group_leave(group);
         //ここはグループ化されてないので待ってない。
         NSLog(@"グループ外_処理1_実行回数:%d %p", i,[NSThread currentThread]);
      });
   }
   
   /*
    * グループ処理2
    */
   dispatch_group_async(group,con_queue, ^{
       NSLog(@"グループ_処理2 %p",[NSThread currentThread]);
   });
   
   //グループ処理完了後の処理
   dispatch_group_notify(group, queue, ^{
       NSLog(@"グループ処理終了後の処理 %p",[NSThread currentThread]);
   });
    
   //グループのblock処理終了まで待機
   dispatch_group_wait(group,DISPATCH_TIME_FOREVER);
   NSLog(@"同期処理:%p",[NSThread currentThread]);

}


・結果はこんな感じです。

labo[23747:3707] グループ_処理1_実行回数:1 0x15595ba0
labo[23747:1803] グループ_処理1_実行回数:0 0x156a8190
labo[23747:1803] グループ_処理1_実行回数:3 0x156a8190
labo[23747:3707] グループ_処理1_実行回数:2 0x15595ba0
labo[23747:1803] グループ_処理1_実行回数:4 0x156a8190
labo[23747:3707] グループ_処理2 0x15595ba0
labo[23747:60b]  同期処理:0x1567ef60
labo[23747:3707] グループ処理終了後の処理 0x15595ba0

この処理では、「同期処理」が実行され、同時に「dispatch_group_notify」が実行されている事が分かります。


・イメージはこんな感じです。

f:id:kassans:20140401114738p:plain