天天看點

GCD排程組實作原理

手動實作排程組
- (void)groupDemo
{
    // 排程組
    dispatch_group_t group = dispatch_group_create();
    // 隊列
    dispatch_queue_t queue = dispatch_get_global_queue(, );

    // 下載下傳圖檔A
    // 1.進入排程組 : 給任務做标記
    dispatch_group_enter(group);
    // 2.讓排程組裡面的任務異步執行
    dispatch_async(queue, ^{
        NSLog(@"下載下傳圖檔A %@",[NSThread currentThread]);

        // 3.移出排程組 : 把标記從排程組移出
        dispatch_group_leave(group);
    });

    // 下載下傳圖檔B
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        NSLog(@"下載下傳圖檔B %@",[NSThread currentThread]);

        dispatch_group_leave(group);
    });

    // 下載下傳圖檔C
    dispatch_group_enter(group);
    dispatch_async(queue, ^{
        NSLog(@"下載下傳圖檔C %@",[NSThread currentThread]);

        dispatch_group_leave(group);
    });

    // 監聽一組異步任務是否執行結束
    dispatch_group_notify(group, queue, ^{
        NSLog(@"三張圖檔下載下傳完了 %@",[NSThread currentThread]);
    });
}
           
使用GCD排程組監聽一組異步任務是否完成
// 使用排程組下載下傳圖檔 : 示範排程組不是用來解決線程安全問題的 
- (void)groupDemo
{
    // 排程組
    dispatch_group_t group = dispatch_group_create();
    // 隊列
    dispatch_queue_t queue = dispatch_get_global_queue(, );

    // 循環的使用排程組去異步的下載下傳圖檔
    for (NSInteger i = ; i < ; i++) {

        // 排程組異步執行的函數 : 會把每個任務都在group裡面做一個标記
        dispatch_group_async(group, queue, ^{

            // 擷取本地圖檔的全路徑
            NSString *name = [NSString stringWithFormat:@"%02zd",(i%)+];
            NSString *filePath = [[NSBundle mainBundle] pathForResource:name ofType:nil];
            // 擷取圖檔
            UIImage *image = [UIImage imageWithContentsOfFile:filePath];

            NSLog(@"%@ %@",name,[NSThread currentThread]);

            // 圖檔下載下傳完成之後,需要緩存到沙盒,如果監聽到這組異步任務執行結束,就在`dispatch_group_notify`方法裡面,重新整理UI
        });
    }

    // 一旦一組異步任務執行結束之後,可以得到統一的通知,這個函數預設在子線程執行的
    // 這個方法不會循環多次的調用,隻會執行一次
    dispatch_group_notify(group, queue, ^{

        // 一組異步任務執行結束之後的操作,寫在這個代碼塊裡面,一般是重新整理UI的,需要回到主線程
        NSLog(@"1000張圖檔執行完了? %@",[NSThread currentThread]);
    });
}