iOS開発におけるGCDのいくつかの使い方

5192 ワード

wait


waitの後の操作は、waitの前のスレッドタスクが操作された後に行われる.waitの前のタスクが非同期であり、同時キューに置かれている(すなわち、非同期実行)としても.コード:
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
    for (NSInteger i = 0; i < 1000; i ++) {
        NSLog(@"%lu", i);
    }
    NSLog(@"waiting...");
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"end");

dispatch_がなければgroup_wait、どうやって印刷したの?endはwaitingの前に印刷されたに違いない.印刷を参照:
   GCD-wait[1071:72264] 997
   GCD-wait[1071:72264] 998
   GCD-wait[1071:72264] 999
   GCD-wait[1071:72264] waitting...
   GCD-wait[1071:72065] end

印刷endは、非同期で実行されるタスクがwaitingを印刷した後に行うことができる.waitを使用すると、現在のスレッドがブロックされます.

barrier


barrierの役割はwaitと同様で、同じキューの前の操作をフェンスのようにブロックし、その後のすべての操作を前のすべての操作が完了してから行うことができます.しかし、waitのように他のスレッドの操作もブロックされません.コード:
dispatch_queue_t queue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_CONCURRENT);
//  ?
//    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
    for (NSInteger i = 0; i < 1000; i ++) {
        NSLog(@"%lu", i);
    }
    NSLog(@"waiting...");
});
dispatch_barrier_async(queue, ^{
    NSLog(@"barrier");
});
dispatch_async(queue, ^{
    NSLog(@"barrier ...");
});

NSLog(@"end");

dispatch_がなければbarrier_asyncはどのように印刷されますか?「waiting」と「barrierの後のタスク...」交互に印刷されているに違いないし、「end」は早く印刷されます.印刷を参照:
 GCD-barrier[1412:136078] end
 GCD-barrier[1412:137056] 0
 GCD-barrier[1412:137056] 1
 GCD-barrier[1412:137056] 998
  
 GCD-barrier[1412:137056] 999
 GCD-barrier[1412:137056] waitting...
 GCD-barrier[1412:137056] barrier
 GCD-barrier[1412:137056] barrier ...

注意:ここの非同期キューはグローバル非同期キューではありません(公式規定)


dispatch_group_notify


同様にnotifyを使用してキュー内のタスクをリスニングし、すべてのタスクが実行された後、notifyの操作を行うことができます.

semaphore


非同期タスクを同期タスクに変換できます.コード:
  __block NSInteger num = 0;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
    for (NSInteger i = 0; i < 1000; i ++) {
        NSLog(@"%lu", i);
        num ++;
    }
    NSLog(@"waiting...");
    dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"num=%lu", num);
NSLog(@"end");

semaphoreendがない場合は必ず事前に印刷され、numは0になります.印刷を参照:
 GCD-Semaphore[1947:219353] 997
 GCD-Semaphore[1947:219353] 998
 GCD-Semaphore[1947:219353] 999
 GCD-Semaphore[1947:219353] waiting...
 GCD-Semaphore[1947:218743] num=1000
 GCD-Semaphore[1947:218743] end

開発中にblockコールバックが必要な場合はsemaphoreを使用してblockの外にコードを置くことができます.
ロックコード:
  - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
for (NSInteger i = 0; i < 100; i ++) {
    [self.mutableArr addObject:@(i)];
}
semaphoreLock = dispatch_semaphore_create(1);
dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue2 = dispatch_queue_create("queue2", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue3 = dispatch_queue_create("queue3", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue1, ^{
    [self nslog];
});
dispatch_async(queue2, ^{
    [self nslog];
});
dispatch_async(queue3, ^{
    [self nslog];
});
}
- (void)nslog{
while (1) {
    //  
    dispatch_semaphore_wait(semaphoreLock, DISPATCH_TIME_FOREVER);
    if (self.mutableArr.count > 0) {
        [self.mutableArr removeObjectAtIndex:0];
        NSLog(@"%lu--%@", self.mutableArr.count, [NSThread currentThread]);
        [NSThread sleepForTimeInterval:0.2];
    }else{
        dispatch_semaphore_signal(semaphoreLock);
        break;
    }
    //  
    dispatch_semaphore_signal(semaphoreLock);
}
}

印刷内容をロックしない場合:
 GCD- [2271:260744] 3--{number = 6, name = (null)}
 GCD- [2271:266057] 2--{number = 4, name = (null)}
 GCD- [2271:266058] 2--{number = 5, name = (null)}
 GCD- [2271:260744] 0--{number = 6, name = (null)}
 GCD- [2271:266057] 1--{number = 4, name = (null)}

印刷されたデータが混乱していることがわかります.ロックをかけなければ、ある瞬間、2つのスレッドが配列中のデータを読み取ったのは1つの要素だけがif判断に入り、そのうちの1つのスレッドが配列中の最後の要素を除去し、配列が空になり、もう1つのスレッドが空の配列を除去操作すると、クラッシュが発生し、スレッドは安全ではないようです.ロックされた印刷:
 GCD- [2428:278050] 4--{number = 5, name = (null)}
 GCD- [2428:278048] 3--{number = 3, name = (null)}
 GCD- [2428:278051] 2--{number = 4, name = (null)}
 GCD- [2428:278050] 1--{number = 5, name = (null)}
 GCD- [2428:278048] 0--{number = 3, name = (null)}

ロックされた印刷データは正常であり、空の配列の操作によってプログラムがクラッシュすることはありません.
この文章はここまで终わって、みんなが残业して给料が多くないことを望んで、男性の同胞はすべて彼女があって、女性の同胞はすべてボーイフレンドがあります.