//NSInvocationOperation NSBlockOperation
/**
操作隊(duì)列(Operation Queues):
這里的隊(duì)列指操作隊(duì)列弓颈,即用來存放操作的隊(duì)列忽肛。不同于 GCD 中的調(diào)度隊(duì)列 FIFO(先進(jìn)先出)的原則。NSOperationQueue 對于添加到隊(duì)列中的操作营勤,首先進(jìn)入準(zhǔn)備就緒的狀態(tài)(就緒狀態(tài)取決于操作之間的依賴關(guān)系),然后進(jìn)入就緒狀態(tài)的操作的開始執(zhí)行順序(非結(jié)束執(zhí)行順序)由操作之間相對的優(yōu)先級決定(優(yōu)先級是操作對象自身的屬性)淹父。
操作隊(duì)列通過設(shè)置最大并發(fā)操作數(shù)(maxConcurrentOperationCount)來控制并發(fā)世蔗、串行。
NSOperationQueue 為我們提供了兩種不同類型的隊(duì)列:主隊(duì)列和自定義隊(duì)列颜矿。主隊(duì)列運(yùn)行在主線程之上,而自定義隊(duì)列在后臺執(zhí)行嫉晶。
*/
/**
NSOperation 實(shí)現(xiàn)多線程的使用步驟分為三步:
創(chuàng)建操作:先將需要執(zhí)行的操作封裝到一個(gè) NSOperation 對象中骑疆。
創(chuàng)建隊(duì)列:創(chuàng)建 NSOperationQueue 對象。
將操作加入到隊(duì)列中:將 NSOperation 對象添加到 NSOperationQueue 對象中替废。
之后呢箍铭,系統(tǒng)就會(huì)自動(dòng)將 NSOperationQueue 中的 NSOperation 取出來,在新線程中執(zhí)行操作椎镣。
*/
// //使用子類 NSInvocationOperation
// // 1.創(chuàng)建 NSInvocationOperation 對象
// NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task1) object:nil];
// // 2.調(diào)用 start 方法開始執(zhí)行操作
// [op start];
// NSLog(@"2---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// // 1.創(chuàng)建 NSBlockOperation 對象
// NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"1---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// //在沒有使用 NSOperationQueue诈火、在主線程中單獨(dú)使用 NSBlockOperation 執(zhí)行一個(gè)操作的情況下,操作是在當(dāng)前線程執(zhí)行的状答,并沒有開啟新線程冷守。
// }
// }];
// NSLog(@"2---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// // 2.調(diào)用 start 方法開始執(zhí)行操作
// [op start];
// NSLog(@"3---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// /**
// * 使用子類 NSBlockOperation
// * 調(diào)用方法 AddExecutionBlock:
// */
// // 1.創(chuàng)建 NSBlockOperation 對象
// NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"1---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
//
// // 2.添加額外的操作
// [op addExecutionBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"2---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
// [op addExecutionBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"3---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
// [op addExecutionBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"4---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
// [op addExecutionBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"5---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
// [op addExecutionBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"6---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
// [op addExecutionBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"7---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
// [op addExecutionBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"8---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
//
// // 3.調(diào)用 start 方法開始執(zhí)行操作
// [op start];
/**
NSOperationQueue 的創(chuàng)建刀崖。
NSOperationQueue 一共有兩種隊(duì)列:主隊(duì)列、自定義隊(duì)列教沾。其中自定義隊(duì)列同時(shí)包含了串行蒲跨、并發(fā)功能译断。下邊是主隊(duì)列授翻、自定義隊(duì)列的基本創(chuàng)建方法和特點(diǎn)。
1 主隊(duì)列
- 凡是添加到主隊(duì)列中的操作孙咪,都會(huì)放到主線程中執(zhí)行(注:不包括操作使用addExecutionBlock:添加的額外操作堪唐,額外操作可能在其他線程執(zhí)行,感謝指正)翎蹈。
2 自定義隊(duì)列(非主隊(duì)列)
- 添加到這種隊(duì)列中的操作淮菠,就會(huì)自動(dòng)放到子線程中執(zhí)行。
- 同時(shí)包含了:串行荤堪、并發(fā)功能合陵。
*/
// /**
// 使用 NSOperation 子類創(chuàng)建操作,并使用 addOperation: 將操作加入到操作隊(duì)列后能夠開啟新線程澄阳,進(jìn)行并發(fā)執(zhí)行拥知。
// */
// // 1.創(chuàng)建自定義隊(duì)列
// NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//
// // 2.創(chuàng)建操作
// // 使用 NSInvocationOperation 創(chuàng)建操作1
// NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task1) object:nil];
//
// // 使用 NSInvocationOperation 創(chuàng)建操作2
// NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task2) object:nil];
//
// // 使用 NSBlockOperation 創(chuàng)建操作3
// NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"3---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
// [op3 addExecutionBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"4---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
//
// // 3.使用 addOperation: 添加所有操作到隊(duì)列中
// [queue addOperation:op1]; // [op1 start]
// [queue addOperation:op2]; // [op2 start]
// [queue addOperation:op3]; // [op3 start]
// /**
// 無需先創(chuàng)建操作,在 block 中添加操作碎赢,直接將包含操作的 block 加入到隊(duì)列中低剔。
// 使用 addOperationWithBlock: 將操作加入到操作隊(duì)列后能夠開啟新線程,進(jìn)行并發(fā)執(zhí)行肮塞。
// */
// // 1.創(chuàng)建隊(duì)列
// NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//
// // 2.使用 addOperationWithBlock: 添加操作到隊(duì)列中
// [queue addOperationWithBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"1---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
// [queue addOperationWithBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"2---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
// [queue addOperationWithBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"3---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
// [queue addOperationWithBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"4---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
/**
NSOperationQueue 控制串行執(zhí)行襟齿、并發(fā)執(zhí)行
NSOperationQueue 創(chuàng)建的自定義隊(duì)列同時(shí)具有串行、并發(fā)功能枕赵,上邊我們演示了并發(fā)功能猜欺,那么他的串行功能是如何實(shí)現(xiàn)的?
這里有個(gè)關(guān)鍵屬性 maxConcurrentOperationCount拷窜,叫做最大并發(fā)操作數(shù)开皿。用來控制一個(gè)特定隊(duì)列中可以有多少個(gè)操作同時(shí)參與并發(fā)執(zhí)行。
注意:這里 maxConcurrentOperationCount 控制的不是并發(fā)線程的數(shù)量装黑,而是一個(gè)隊(duì)列中同時(shí)能并發(fā)執(zhí)行的最大操作數(shù)副瀑。而且一個(gè)操作也并非只能在一個(gè)線程中運(yùn)行。
maxConcurrentOperationCount 默認(rèn)情況下為-1恋谭,表示不進(jìn)行限制糠睡,可進(jìn)行并發(fā)執(zhí)行。
maxConcurrentOperationCount 為1時(shí)疚颊,隊(duì)列為串行隊(duì)列狈孔。只能串行執(zhí)行信认。
maxConcurrentOperationCount 大于1時(shí),隊(duì)列為并發(fā)隊(duì)列均抽。操作并發(fā)執(zhí)行嫁赏,當(dāng)然這個(gè)值不應(yīng)超過系統(tǒng)限制,即使自己設(shè)置一個(gè)很大的值油挥,系統(tǒng)也會(huì)自動(dòng)調(diào)整為 min{自己設(shè)定的值潦蝇,系統(tǒng)設(shè)定的默認(rèn)最大值}。
*/
/**
設(shè)置 MaxConcurrentOperationCount(最大并發(fā)操作數(shù))
*/
// // 1.創(chuàng)建隊(duì)列
// NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//
// // 2.設(shè)置最大并發(fā)操作數(shù)
// queue.maxConcurrentOperationCount = 1; // 串行隊(duì)列
//// queue.maxConcurrentOperationCount = 2; // 并發(fā)隊(duì)列
//// queue.maxConcurrentOperationCount = 8; // 并發(fā)隊(duì)列
//
// // 3.添加操作
// [queue addOperationWithBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"1---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
// [queue addOperationWithBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"2---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
// [queue addOperationWithBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"3---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
// [queue addOperationWithBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"4---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
// [queue addOperationWithBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"5---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
/**
NSOperation 操作依賴
NSOperation深寥、NSOperationQueue 最吸引人的地方是它能添加操作之間的依賴關(guān)系攘乒。通過操作依賴,我們可以很方便的控制操作之間的執(zhí)行先后順序惋鹅。
NSOperation提供了3個(gè)接口供我們管理和查看依賴则酝。
- (void)addDependency:(NSOperation *)op; 添加依賴,使當(dāng)前操作依賴于操作 op 的完成闰集。
- (void)removeDependency:(NSOperation *)op; 移除依賴沽讹,取消當(dāng)前操作對操作 op 的依賴。
@property (readonly, copy) NSArray<NSOperation *> *dependencies; 在當(dāng)前操作開始執(zhí)行之前完成執(zhí)行的所有操作對象數(shù)組武鲁。
當(dāng)然爽雄,我們經(jīng)常用到的還是添加依賴操作。現(xiàn)在考慮這樣的需求洞坑,比如說有 A盲链、B 兩個(gè)操作,其中 A 執(zhí)行完操作迟杂,B 才能執(zhí)行操作刽沾。
*/
/**
操作依賴
使用方法:addDependency:
操作結(jié)果: 通過添加操作依賴,無論運(yùn)行幾次排拷,其結(jié)果都是 op1 先執(zhí)行侧漓,op2 后執(zhí)行。
*/
// //1 創(chuàng)建隊(duì)列
// NSOperationQueue *queue = [[NSOperationQueue alloc]init];
// //2 創(chuàng)建操作
// NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"1---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
// NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"2---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// }];
//
// //3 添加依賴
// [op2 addDependency:op1];
//
// //4 添加操作到隊(duì)列中
// [queue addOperation:op1];
// [queue addOperation:op2];
//
/**
NSOperation 優(yōu)先級
NSOperation 提供了queuePriority(優(yōu)先級)屬性监氢,queuePriority屬性適用于同一操作隊(duì)列中的操作布蔗,不適用于不同操作隊(duì)列中的操作。默認(rèn)情況下浪腐,所有新創(chuàng)建的操作對象優(yōu)先級都是NSOperationQueuePriorityNormal纵揍。但是我們可以通過setQueuePriority:方法來改變當(dāng)前操作在同一隊(duì)列中的執(zhí)行優(yōu)先級
// 優(yōu)先級的取值
typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {
NSOperationQueuePriorityVeryLow = -8L,
NSOperationQueuePriorityLow = -4L,
NSOperationQueuePriorityNormal = 0,
NSOperationQueuePriorityHigh = 4,
NSOperationQueuePriorityVeryHigh = 8
};
對于添加到隊(duì)列中的操作,首先進(jìn)入準(zhǔn)備就緒的狀態(tài)(就緒狀態(tài)取決于操作之間的依賴關(guān)系)议街,然后進(jìn)入就緒狀態(tài)的操作的開始執(zhí)行順序(非結(jié)束執(zhí)行順序)由操作之間相對的優(yōu)先級決定(優(yōu)先級是操作對象自身的屬性)泽谨。
那么,什么樣的操作才是進(jìn)入就緒狀態(tài)的操作呢?
當(dāng)一個(gè)操作的所有依賴都已經(jīng)完成時(shí)吧雹,操作對象通常會(huì)進(jìn)入準(zhǔn)備就緒狀態(tài)骨杂,等待執(zhí)行。
舉個(gè)例子雄卷,現(xiàn)在有4個(gè)優(yōu)先級都是 NSOperationQueuePriorityNormal(默認(rèn)級別)的操作:op1搓蚪,op2,op3丁鹉,op4妒潭。其中 op3 依賴于 op2,op2 依賴于 op1鳄炉,即 op3 -> op2 -> op1《虐遥現(xiàn)在將這4個(gè)操作添加到隊(duì)列中并發(fā)執(zhí)行搜骡。
因?yàn)?op1 和 op4 都沒有需要依賴的操作拂盯,所以在 op1,op4 執(zhí)行之前记靡,就是處于準(zhǔn)備就緒狀態(tài)的操作谈竿。
而 op3 和 op2 都有依賴的操作(op3 依賴于 op2,op2 依賴于 op1)摸吠,所以 op3 和 op2 都不是準(zhǔn)備就緒狀態(tài)下的操作空凸。
*/
/**
NSOperation、NSOperationQueue 線程間的通信在 iOS 開發(fā)過程中寸痢,我們一般在主線程里邊進(jìn)行 UI 刷新呀洲,例如:點(diǎn)擊、滾動(dòng)啼止、拖拽等事件道逗。我們通常把一些耗時(shí)的操作放在其他線程,比如說圖片下載献烦、文件上傳等耗時(shí)操作滓窍。而當(dāng)我們有時(shí)候在其他線程完成了耗時(shí)操作時(shí),需要回到主線程巩那,那么就用到了線程之間的通訊吏夯。
*/
/**
線程間通信
通過線程間的通信,先在其他線程中執(zhí)行操作即横,等操作執(zhí)行完了之后再回到主線程執(zhí)行主線程的相應(yīng)操作噪生。
*/
// //1 創(chuàng)建隊(duì)列
// NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//
// //2 添加操作
// [queue addOperationWithBlock:^{
// // 異步進(jìn)行耗時(shí)操作
// for (int i = 0; i < 2; i++) {
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"1---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }
// //回到主線程
// [[NSOperationQueue mainQueue] addOperationWithBlock:^{
// // 進(jìn)行一些 UI 刷新等操作
// NSLog(@"2---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }];
// }];
/**
NSOperation、NSOperationQueue 線程同步和線程安全
線程安全:如果你的代碼所在的進(jìn)程中有多個(gè)線程在同時(shí)運(yùn)行东囚,而這些線程可能會(huì)同時(shí)運(yùn)行這段代碼跺嗽。如果每次運(yùn)行結(jié)果和單線程運(yùn)行的結(jié)果是一樣的,而且其他的變量的值也和預(yù)期的是一樣的,就是線程安全的抛蚁。
若每個(gè)線程中對全局變量陈醒、靜態(tài)變量只有讀操作,而無寫操作瞧甩,一般來說钉跷,這個(gè)全局變量是線程安全的;若有多個(gè)線程同時(shí)執(zhí)行寫操作(更改變量)肚逸,一般都需要考慮線程同步爷辙,否則的話就可能影響線程安全。
線程同步:可理解為線程 A 和 線程 B 一塊配合朦促,A 執(zhí)行到一定程度時(shí)要依靠線程 B 的某個(gè)結(jié)果膝晾,于是停下來,示意 B 運(yùn)行务冕;B 依言執(zhí)行血当,再將結(jié)果給 A;A 再繼續(xù)操作禀忆。
*/
/**
下面臊旭,我們模擬火車票售賣的方式,實(shí)現(xiàn) NSOperation 線程安全和解決線程同步問題箩退。
場景:總共有50張火車票离熏,有兩個(gè)售賣火車票的窗口,一個(gè)是北京火車票售賣窗口戴涝,另一個(gè)是上鹤檀粒火車票售賣窗口。兩個(gè)窗口同時(shí)售賣火車票啥刻,賣完為止奸鸯。
*/
/**先來看看不考慮線程安全的代碼:*/
// self.ticketSurplusCount = 50;
//
// // 1.創(chuàng)建 queue1,queue1 代表北京火車票售賣窗口
// NSOperationQueue *queue1 = [[NSOperationQueue alloc] init];
// queue1.maxConcurrentOperationCount = 1;
//
// // 2.創(chuàng)建 queue2,queue2 代表上海火車票售賣窗口
// NSOperationQueue *queue2 = [[NSOperationQueue alloc] init];
// queue2.maxConcurrentOperationCount = 1;
//
// // 3.創(chuàng)建賣票操作 op1
// NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
// [self saleTicketNotSafe];
// }];
//
// // 4.創(chuàng)建賣票操作 op2
// NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
// [self saleTicketNotSafe];
// }];
//
// // 5.添加操作郑什,開始賣票
// [queue1 addOperation:op1];
// [queue2 addOperation:op2];
/**
NSOperation府喳、NSOperationQueue 線程安全
線程安全解決方案:可以給線程加鎖,在一個(gè)線程執(zhí)行該操作的時(shí)候蘑拯,不允許其他線程進(jìn)行操作钝满。iOS 實(shí)現(xiàn)線程加鎖有很多種方式。@synchronized申窘、 NSLock弯蚜、NSRecursiveLock、NSCondition剃法、NSConditionLock碎捺、pthread_mutex、dispatch_semaphore、OSSpinLock收厨、atomic(property) set/ge等等各種方式晋柱。這里我們使用 NSLock 對象來解決線程同步問題。NSLock 對象可以通過進(jìn)入鎖時(shí)調(diào)用 lock 方法诵叁,解鎖時(shí)調(diào)用 unlock 方法來保證線程安全雁竞。
*/
// self.ticketSurplusCount = 50;
//
// self.lock = [[NSLock alloc] init]; // 初始化 NSLock 對象
//
// // 1.創(chuàng)建 queue1,queue1 代表北京火車票售賣窗口
// NSOperationQueue *queue1 = [[NSOperationQueue alloc] init];
// queue1.maxConcurrentOperationCount = 1;
//
// // 2.創(chuàng)建 queue2,queue2 代表上海火車票售賣窗口
// NSOperationQueue *queue2 = [[NSOperationQueue alloc] init];
// queue2.maxConcurrentOperationCount = 1;
//
// // 3.創(chuàng)建賣票操作 op1
// NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
// [self saleTicketSafe];
// }];
//
// // 4.創(chuàng)建賣票操作 op2
// NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
// [self saleTicketSafe];
// }];
//
// // 5.添加操作拧额,開始賣票
// [queue1 addOperation:op1];
// [queue2 addOperation:op2];
// // 1.創(chuàng)建隊(duì)列
// NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//
// // 2.設(shè)置最大并發(fā)操作數(shù)
//// queue.maxConcurrentOperationCount = -1; // 并行隊(duì)列
//
// // 3.添加操作
// NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
// NSLog(@"op1 start");
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// NSLog(@"1---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// });
// NSLog(@"op1 end");
// }];
// NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
// NSLog(@"op2 start");
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// NSLog(@"2---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// });
// NSLog(@"op2 end");
// }];
// NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"3---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }];
// NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"4---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }];
// NSBlockOperation *op5 = [NSBlockOperation blockOperationWithBlock:^{
// [NSThread sleepForTimeInterval:2]; // 模擬耗時(shí)操作
// NSLog(@"5---%@", [NSThread currentThread]); // 打印當(dāng)前線程
// }];
//
// [op2 addDependency:op1];
// //
// [queue addOperations:@[op1] waitUntilFinished:true];
// [queue addOperations:@[op2] waitUntilFinished:true];
// [queue addOperation:op3];
// [queue addOperation:op4];
// [queue addOperation:op5];
// [op1 waitUntilFinished];
//
// [op3 cancel];
iOS中的NSOperation和NSOperationQueue
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
- 文/潘曉璐 我一進(jìn)店門祸泪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人建芙,你說我怎么就攤上這事《螅” “怎么了禁荸?”我有些...
- 文/不壞的土叔 我叫張陵,是天一觀的道長阀湿。 經(jīng)常有香客問我赶熟,道長,這世上最難降的妖魔是什么陷嘴? 我笑而不...
- 正文 為了忘掉前任映砖,我火速辦了婚禮,結(jié)果婚禮上灾挨,老公的妹妹穿的比我還像新娘邑退。我一直安慰自己,他們只是感情好劳澄,可當(dāng)我...
- 文/花漫 我一把揭開白布地技。 她就那樣靜靜地躺著,像睡著了一般秒拔。 火紅的嫁衣襯著肌膚如雪莫矗。 梳的紋絲不亂的頭發(fā)上,一...
- 文/蒼蘭香墨 我猛地睜開眼彬伦,長吁一口氣:“原來是場噩夢啊……” “哼滔悉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起单绑,我...
- 序言:老撾萬榮一對情侶失蹤回官,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后搂橙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體歉提,經(jīng)...
- 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
- 正文 我和宋清朗相戀三年区转,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了苔巨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
- 正文 年R本政府宣布,位于F島的核電站肖方,受9級特大地震影響闺魏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜俯画,卻給世界環(huán)境...
- 文/蒙蒙 一析桥、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧艰垂,春花似錦泡仗、人聲如沸。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至拉宗,卻和暖如春峦树,著一層夾襖步出監(jiān)牢的瞬間辣辫,已是汗流浹背。 一陣腳步聲響...
- 正文 我出身青樓谷遂,卻偏偏與公主長得像葬馋,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子肾扰,可洞房花燭夜當(dāng)晚...