GCD 與 NSOperation 的區別 ?xcode
1. GCD 是基於 C 語言寫的核心服務, 很是簡單高效, 而 NSOperation 是基於 GCD 的一種封裝,抽象出來的對象, 因此通常狀況下對於任務的依賴和併發數沒有要求的狀況下, GCD 的效率更高, 開銷更小多線程
2. 依賴關係,NSOperation能夠設置兩個NSOperation之間的依賴,第二個任務依賴於第一個任務完成執行,GCD沒法設置依賴關係,不過能夠經過dispatch_barrier_async來實現這種效果併發
3. KVO(鍵值對觀察),NSOperation和容易判斷Operation當前的狀態(是否執行,是否取消),對此GCD沒法經過KVO進行判斷異步
4. 優先級,NSOperation能夠設置自身的優先級,可是優先級高的不必定先執行,GCD只能設置隊列的優先級,沒法在執行的block設置優先級;async
5. 繼承,NSOperation是一個抽象類實際開發中經常使用的兩個類是NSInvocationOperation和NSBlockOperation,一樣咱們能夠自定義NSOperation,GCD執行任務能夠自由組裝,沒有繼承那麼高的代碼複用度;函數
總的來講: 若是對於任務的併發數和任務之間的依賴關係沒有要求, 能夠直接使用 GCD, 不然使用 NSOperation 能夠知足對任務的控制ui
GCDspa
GCD 面對的不是線程, GCD 面對的只有隊列和任務這兩個概念, 你不用管在哪一個線程, 只須要把任務按正確的同步/異步的方式添加進串行/併發隊列便可線程
同步 異步code
主隊列 死鎖 不會開啓新線程(順序執行)
串行隊列 在當前線程執行(順序執行) 開啓一個新的線程(順序執行)
併發隊列 在當前線程執行(順序執行) 開啓一個或多個線程(併發執行)
下面是例子
//異步 + 並行隊列
- (
void
)asyncConcurrent{
//建立一個並行隊列
dispatch_queue_t queue = dispatch_queue_create(
"標識符"
, DISPATCH_QUEUE_CONCURRENT);
NSLog(@
"---start---"
);
//使用異步函數封裝三個任務
dispatch_async(queue, ^{
NSLog(@
"任務1---%@"
, [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@
"任務2---%@"
, [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@
"任務3---%@"
, [NSThread currentThread]);
});
NSLog(@
"---end---"
);
}
結果: start end 3 2 1 // 開啓3個新的線程 同時執行的 沒有前後
//異步 + 串行隊列
- (
void
)asyncSerial{
//建立一個串行隊列
dispatch_queue_t queue = dispatch_queue_create(
"標識符"
, DISPATCH_QUEUE_SERIAL);
NSLog(@
"---start---"
);
//使用異步函數封裝三個任務
dispatch_async(queue, ^{
NSLog(@
"任務1---%@"
, [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@
"任務2---%@"
, [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@
"任務3---%@"
, [NSThread currentThread]);
});
NSLog(@
"---end---"
);
}
// 結果 start end 123 開啓一個新的線程 順序執行
//同步 + 並行隊列
- (
void
)syncConcurrent{
//建立一個並行隊列
dispatch_queue_t queue = dispatch_queue_create(
"標識符"
, DISPATCH_QUEUE_CONCURRENT);
NSLog(@
"---start---"
);
//使用同步函數封裝三個任務
dispatch_sync(queue, ^{
NSLog(@
"任務1---%@"
, [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@
"任務2---%@"
, [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@
"任務3---%@"
, [NSThread currentThread]);
});
NSLog(@
"---end---"
);
- (
void
)syncSerial{
//建立一個串行隊列
dispatch_queue_t queue = dispatch_queue_create(
"標識符"
, DISPATCH_QUEUE_SERIAL);
NSLog(@
"---start---"
);
//使用異步函數封裝三個任務
dispatch_sync(queue, ^{
NSLog(@
"任務1---%@"
, [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@
"任務2---%@"
, [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@
"任務3---%@"
, [NSThread currentThread]);
});
NSLog(@
"---end---"
);
}
- (
void
)asyncMain{
//獲取主隊列
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@
"---start---"
);
//使用異步函數封裝三個任務
dispatch_async(queue, ^{
NSLog(@
"任務1---%@"
, [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@
"任務2---%@"
, [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@
"任務3---%@"
, [NSThread currentThread]);
});
NSLog(@
"---end---"
);
}
});
以後呢,系統就會自動將 NSOperationQueue 中的 NSOperation 取出來,在新線程中執行操做
先看看NSInvocationOperation的使用:
1. 同步執行的 直接操做 不加入 queue
再看看NSBlockOperation:
22 NSBlockOperation *operation=[NSBlockOperation blockOperationWithBlock:^{ 23 NSLog(@"NSBlockOperation------%@",[NSThread currentThread]); 24 }]; 25 26 //添加操做 在子線程異步執行 27 [operation addExecutionBlock:^{ 28 NSLog(@"NSBlockOperation1------%@",[NSThread currentThread]); 29 }]; 30
// 在子線程 異步執行 31 [operation addExecutionBlock:^{ 32 NSLog(@"NSBlockOperation2------%@",[NSThread currentThread]); 33 }]; 34 35 //開啓執行操做 36 [operation start];
// 設置最大併發數
// 1.建立隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 2.設置最大併發操做數
queue.maxConcurrentOperationCount =
1
;
// 串行隊列
// queue.maxConcurrentOperationCount = 2; // 併發隊列
// queue.maxConcurrentOperationCount = 8; // 併發隊列
// 3.添加操做
[queue addOperationWithBlock:^{
for
(
int
i =
0
; i <
2
; i++) {
[NSThread sleepForTimeInterval:
2
];
// 模擬耗時操做
NSLog(@
"1---%@"
, [NSThread currentThread]);
// 打印當前線程
}
}];
[queue addOperationWithBlock:^{
for
(
int
i =
0
; i <
2
; i++) {
[NSThread sleepForTimeInterval:
2
];
// 模擬耗時操做
NSLog(@
"2---%@"
, [NSThread currentThread]);
// 打印當前線程
}
}];
[queue addOperationWithBlock:^{
for
(
int
i =
0
; i <
2
; i++) {
[NSThread sleepForTimeInterval:
2
];
// 模擬耗時操做
NSLog(@
"3---%@"
, [NSThread currentThread]);
// 打印當前線程
}
}];
[queue addOperationWithBlock:^{
for
(
int
i =
0
; i <
2
; i++) {
[NSThread sleepForTimeInterval:
2
];
// 模擬耗時操做
NSLog(@
"4---%@"
, [NSThread currentThread]);
// 打印當前線程
}
}];
NSBlockOperation最開始的任務是在主線程中執行的,再給NSBlockOperation添加的額外的任務是在子線程中執行的,程序自動幫助開啓了子線程。
GCD隊列和NSOperationQueue隊列類型比較:
GCD的隊列類型:
(1)併發隊列:a.全局 b.本身建立的
(2)串行隊列:a.主隊列 b.本身建立的
NSOperationQueue隊列類型:
(1)主隊列[NSOperationQueue mainQueue],添加到主隊列中的任務,都會在主線程中執行。
(2)其餘隊列(串行、併發),添加到其餘隊列中的任務,都會自動放在子線程中執行。
NSOperation默認是同步執行的。
建立一個 operation 直接 start 執行的話會在 main thread , 再添加額外的block 任務的時候會開啓新的線程異步執行
建立一個 operation 和 queue 並把 operation 放進 queue 會自動放進子線程