iOS 多執行緒筆記

Harvie_Z發表於2019-03-12

GCD

同步函式

dispatch_sync(queue, ^{
    NSLog(@"---download1---%@",[NSThread currentThread]);
});
複製程式碼

非同步函式,具有開啟執行緒的能力

dispatch_async(queue, ^{
    NSLog(@"---download1---%@",[NSThread currentThread]);
});
複製程式碼

序列佇列,任務序列執行

dispatch_queue_t queue = dispatch_queue_create("queueID", DISPATCH_QUEUE_SERIAL);
複製程式碼

並行佇列,任務可併發執行

dispatch_queue_t queue = dispatch_queue_create("queueID", DISPATCH_QUEUE_CONCURRENT);
複製程式碼

全域性併發佇列

dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
複製程式碼

主佇列

dispatch_queue_t queue =  dispatch_get_main_queue();
複製程式碼

任務併發執行必須併發佇列 + 非同步函式

dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 或者
//dispatch_queue_t queue = dispatch_queue_create("queueID", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
    NSLog(@"---download1---%@",[NSThread currentThread]);
});
    
dispatch_sync(queue, ^{
    NSLog(@"---download2---%@",[NSThread currentThread]);
});
    
dispatch_sync(queue, ^{
    NSLog(@"---download3---%@",[NSThread currentThread]);
});

複製程式碼

佇列組:多個任務執行完成再做其他操作。

//建立佇列組
dispatch_group_t group =  dispatch_group_create();
dispatch_group_async(group, queue, ^{
    NSLog(@"任務1");
});
  
//下載圖片2
dispatch_group_async(group, queue, ^{
    NSLog(@"任務2");
});
    
//合成
dispatch_group_notify(group, queue, ^{
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"%@--重新整理UI",[NSThread currentThread]);
    });
});
複製程式碼

快速迭代

dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index){
    // 執行10次程式碼,index順序不確定
});
複製程式碼

柵欄函式:等柵欄函式前的任務執行完再執行後面的任務

//1.建立佇列(併發佇列)
dispatch_queue_t queue = dispatch_queue_create("com.downloadqueue", DISPATCH_QUEUE_CONCURRENT);
    
dispatch_async(queue, ^{
    
    for (NSInteger i = 0; i<10; i++) {
        NSLog(@"%zd-download1--%@",i,[NSThread currentThread]);
    }
});
    
dispatch_async(queue, ^{
    
    for (NSInteger i = 0; i<10; i++) {
        NSLog(@"%zd-download2--%@",i,[NSThread currentThread]);
    }
});
    
//柵欄函式
dispatch_barrier_async(queue, ^{
    NSLog(@"我是一個柵欄函式");
});
    
dispatch_async(queue, ^{
    
    for (NSInteger i = 0; i<10; i++) {
        NSLog(@"%zd-download3--%@",i,[NSThread currentThread]);
    }
});
    
dispatch_async(queue, ^{
    
    for (NSInteger i = 0; i<10; i++) {
        NSLog(@"%zd-download4--%@",i,[NSThread currentThread]);
    }
});
複製程式碼

NSOperation:抽象類,需要使用它的子類

// NSInvocationOperation
/*
 第一個引數:目標物件
 第二個引數:該操作要呼叫的方法,最多接受一個引數
 第三個引數:呼叫方法傳遞的引數,如果方法不接受引數,那麼該值傳nil
 */
NSInvocationOperation *operation = [[NSInvocationOperation alloc]
                                    initWithTarget:self selector:@selector(run) object:nil];

//2.啟動操作
[operation start];

// NSBlockOperation
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    //在主執行緒中執行
    NSLog(@"---download1--%@",[NSThread currentThread]);
}];
    
//2.追加操作,追加的操作在子執行緒中執行
[operation addExecutionBlock:^{
    NSLog(@"---download2--%@",[NSThread currentThread]);
}];
    
//3.啟動執行操作
[operation start];
複製程式碼

預設情況下,呼叫例項物件的start方法並不會開啟新執行緒執行任務,而需要將其加入NSOperationQueue中。

//1.建立佇列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    
//2.封裝操作
NSInvocationOperation *op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download1) object:nil];
    
NSInvocationOperation *op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download2) object:nil];
    
//3.把封裝好的操作新增到佇列中
[queue addOperation:op1];//會自動執行[op1 start]
[queue addOperation:op2];
複製程式碼

設定最大併發數

非主佇列中的任務預設是併發執行的,可以通過設定佇列的最大併發數來控制該佇列中的任務是併發執行還是序列執行的.
當最大併發數==1 任務序列執行
當最大併發數>1 任務併發執行
系統預設的最大併發數 == -1 (預設是併發執行的)
當最大併發數 == 0 不會執行任務操作

//0.建立佇列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
queue.maxConcurrentOperationCount = 1;
複製程式碼

取消佇列中的所有任務

NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[queue cancelAllOperations];
複製程式碼

佇列的暫停和恢復

暫停佇列的時候,不能暫停當前正在執行的任務,當前任務還是會繼續執行完,但是下一個任務將不會執行。
暫停操作是可以恢復的。

NSOperationQueue *queue = [[NSOperationQueue alloc]init];
// 暫停
queue.suspended = YES;
// 恢復
queue.suspended = NO;
複製程式碼

操作依賴:操作A執行完後,才能執行操作B

//1.建立佇列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
NSOperationQueue *queueOther = [[NSOperationQueue alloc]init];

NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"download1 ---%@",[NSThread currentThread]);
}];
    
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"download2 ---%@",[NSThread currentThread]);
}];
//操作監聽,當對應的任務執行完畢後,可以在block裡面執行相關的掃尾操作
op2.completionBlock = ^{
    
    //注意:執行該block塊程式碼的執行緒和執行op2操作的執行緒不一定一致,使用GCD和NSOperation技術執行緒的分配是系統內部決定的
    NSLog(@"任務op2已經執行完畢--%@",[NSThread currentThread]);
};

NSBlockOperation *op01 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"任務01---%@",[NSThread currentThread]);
}];
    
NSBlockOperation *op02 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"任務02---%@",[NSThread currentThread]);
}];

[op1 addDependency:op2];
//跨佇列依賴
[op1 addDependency:op01];
[op02 addDependency:op1];

// 新增操作到相應的佇列
[queue addOperation:op1];
[queue addOperation:op2];
    
[queueOther addOperation:op01];
[queueOther addOperation:op02];
複製程式碼

相關文章