- 配合使用NSOperation和NSOperationQueue也能實(shí)現(xiàn)多線程編程
- NSOperation是個(gè)抽象類,并不具備封裝操作的能力,必須使用它的子類
- NSInvocationOperation
- NSBlockOperation
- 自定義子類繼承NSOperation,實(shí)現(xiàn)內(nèi)部相應(yīng)的
main方法
- NSOperationQueue的作用
- NSOperation可以調(diào)用start方法來執(zhí)行任務(wù),但默認(rèn)是同步執(zhí)行的
- 如果將NSOperation添加到NSOperationQueue(操作隊(duì)列)中,系統(tǒng)會(huì)自動(dòng)異步執(zhí)行NSOperation中的操作
- 添加方法1:- (void)addOperation:(NSOperation *)op;
- 添加方法2:- (void)addOperationWithBlock:(void (^)(void))block;
- NSOperation是個(gè)抽象類,并不具備封裝操作的能力,必須使用它的子類
- 使用NSInvocationOperation實(shí)現(xiàn)多線程編程
- 步驟:
- 封裝操作
initWithTarget - 實(shí)現(xiàn)操作對(duì)應(yīng)的方法
sel - 啟動(dòng)操作
start
- 封裝操作
-
注意- 默認(rèn)情況下,調(diào)用了start方法后并不會(huì)開一條新線程去執(zhí)行操作,而是在當(dāng)前線程同步執(zhí)行操作
- 只有將NSOperation放到一個(gè)NSOperationQueue中,才會(huì)異步執(zhí)行操作
- 步驟:
- 使用NSBlockOperation實(shí)現(xiàn)多線程編程
- 步驟:
- 封裝操作
blockOperationWithBlock - 追加操作
addExecutionBlock:(此步驟可以省略,即可以追加操作也可以不追加操作) - 啟動(dòng)操作
start
- 封裝操作
-
注意- 只要NSBlockOperation封裝的操作數(shù)>1,就會(huì)異步執(zhí)行操作
- 即只有追加操作,才會(huì)異步執(zhí)行操作
- 步驟:
- 自定義子類繼承NSOperation,實(shí)現(xiàn)內(nèi)部相應(yīng)的
main方法- 創(chuàng)建自定義的子類繼承NSOperation
- 在子類中實(shí)現(xiàn)內(nèi)部相應(yīng)的
main方法- 自己創(chuàng)建自動(dòng)釋放池(因?yàn)槿绻钱惒讲僮鳎瑹o法訪問主線程的自動(dòng)釋放池)
- 經(jīng)常通過-(BOOL)isCancelled方法檢測(cè)操作是否被取消,對(duì)取消做出響應(yīng)
- 實(shí)例化子類對(duì)象,并實(shí)現(xiàn)操作
- 使用NSInvocationOperation和NSOperationQueue實(shí)現(xiàn)多線程編程
- 步驟
- 封裝操作
- 創(chuàng)建隊(duì)列
- 主隊(duì)列
mainQueue(凡是在主隊(duì)列中的任務(wù)都在主線程中執(zhí)行&串行隊(duì)列) - 非主隊(duì)列
[[NSOperationQueue alloc]init](同時(shí)具備了并發(fā)和串行的功能,默認(rèn)是并發(fā)隊(duì)列)
- 主隊(duì)列
- 把操作添加到隊(duì)列中
- addOperation:
- addOperationWithBlock:
- 步驟
- 并發(fā)數(shù)
- 概念:同時(shí)執(zhí)行的任務(wù)數(shù)
- 必須在操作添加到隊(duì)列之前設(shè)置最大并發(fā)數(shù)的個(gè)數(shù)
- 最大并發(fā)數(shù)的方法
- (NSInteger)maxConcurrentOperationCount;
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;
- 最大并發(fā)數(shù)量
- maxConcurrentOperationCount = 1 串行隊(duì)列
- maxConcurrentOperationCount > 1 并發(fā)隊(duì)列
- maxConcurrentOperationCount = -1 并發(fā)數(shù)不做限制,并發(fā)隊(duì)列
- maxConcurrentOperationCount = 0 程序不能運(yùn)行
- 同步執(zhí)行任務(wù)的情況
- 僅使用NSInvocationOperation
- 僅使用NSBlockOperation
- 使用NSOperation和mainQueue
- 使用NSOperation和[[NSOperationQueue alloc]init]且最大并發(fā)數(shù)為0
- 隊(duì)列的暫停、恢復(fù)、取消
- 隊(duì)列的暫停
- -(void)setSuspended:(BOOL)b; // YES代表暫停隊(duì)列,NO代表恢復(fù)隊(duì)列
- -(BOOL)isSuspended;
- 不能暫停當(dāng)前處于執(zhí)行狀態(tài)的操作
- 只能停止后面沒有處于執(zhí)行狀態(tài)的操作
- 暫停操作是可以恢復(fù)的
- 隊(duì)列的恢復(fù)
- -(void)setSuspended:(BOOL)b; // YES代表暫停隊(duì)列,NO代表恢復(fù)隊(duì)列
- -(BOOL)isSuspended;
- 隊(duì)列的取消
- 取消所有隊(duì)列的操作-(void)cancelAllOperations;,內(nèi)部調(diào)用每個(gè)操作的cancel方法
- 調(diào)用NSOperation的- (void)cancel方法取消單個(gè)操作
- 后面的任務(wù)將永遠(yuǎn)沒有機(jī)會(huì)執(zhí)行
- 取消操作是不能恢復(fù)的
- 實(shí)現(xiàn)步驟
- 在storyboard中拖拽開始執(zhí)行、暫停、取消、恢復(fù)4個(gè)按鈕
- 生成其對(duì)應(yīng)的點(diǎn)擊事件的方法
- 開始執(zhí)行方法
- 使用NSBlockOperation封裝操作
- 創(chuàng)建隊(duì)列
- 設(shè)置最大并發(fā)數(shù)為1(保證程序串行執(zhí)行)
- 把操作添加到隊(duì)列
- 暫停方法
- 設(shè)置isSuspended屬性為YES
- 取消方法
- 調(diào)用cancelAllOperations方法
- 恢復(fù)方法
- 設(shè)置isSuspended屬性為NO
- 實(shí)現(xiàn)代碼
- 隊(duì)列的暫停
@interface ViewController ()
/** 隊(duì)列 */
@property(nonatomic, strong)NSOperationQueue *queue;
@end
@implementation ViewController
/**
* 開始執(zhí)行
*/
- (IBAction)startBtnClick {
// 創(chuàng)建操作對(duì)象
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 10000; i++) {
NSLog(@"1---%zd---main------%@", i,[NSThread currentThread]);
}
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 10000; i++) {
NSLog(@"2---%zd---main------%@", i,[NSThread currentThread]);
}
}];
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 10000; i++) {
NSLog(@"3---%zd---main------%@", i,[NSThread currentThread]);
}
}];
// 創(chuàng)建隊(duì)列
self.queue = [[NSOperationQueue alloc] init];
// 設(shè)置最大并發(fā)數(shù)
self.queue.maxConcurrentOperationCount = 1;
// 把操作添加到隊(duì)列
[self.queue addOperation:op1];
[self.queue addOperation:op2];
[self.queue addOperation:op3];
}
/**
* 暫停
*/
- (IBAction)suspendBtnClick {
[self.queue setSuspended:YES];
}
/**
* 取消
*/
- (IBAction)cancleBtnClick {
[self.queue cancelAllOperations];
}
/**
* 恢復(fù)
*/
- (IBAction)resumeBtnClick {
[self.queue setSuspended:NO];
}
@end
- 自定義NSOperatioin子類實(shí)現(xiàn)隊(duì)列的取消
- 自定義NSOperatioin子類
- 重寫main方法
- 在storyboard中拖拽開始執(zhí)行、取消2個(gè)按鈕
- 生成其對(duì)應(yīng)的點(diǎn)擊事件的方法
- 開始執(zhí)行方法
- 使用自定義NSOperatioin子類封裝操作
- 創(chuàng)建隊(duì)列
- 設(shè)置最大并發(fā)數(shù)為1(保證程序串行執(zhí)行)
- 把操作添加到隊(duì)列
- 取消方法
- 調(diào)用cancelAllOperations方法
- 代碼實(shí)現(xiàn)
// 控制器代碼
@interface ViewController ()
/** 隊(duì)列 */
@property(nonatomic, strong)NSOperationQueue *queue;
@end
@implementation ViewController
- (IBAction)startBtnClick {
// 封裝操作
ZQOperation *op = [[ZQOperation alloc] init];
// 創(chuàng)建隊(duì)列
self.queue = [[NSOperationQueue alloc] init];
// 設(shè)置最大并發(fā)數(shù)
self.queue.maxConcurrentOperationCount = 1;
// 把操作添加到隊(duì)列
[self.queue addOperation:op];
}
- (IBAction)cancelBtnClick {
[self.queue cancelAllOperations];
}
@end
-
操作的依賴、監(jiān)聽
- 操作的依賴
- NSOperation之間可以設(shè)置依賴來保證執(zhí)行順序
- 可以在不同queue的NSOperation之間創(chuàng)建依賴關(guān)系
- [operationB addDependency:operationA]; // 操作B依賴于操作A
- 不能設(shè)置循環(huán)依賴:A依賴B,B依賴A
- 設(shè)置依賴必須再把操作添加到隊(duì)列之前
- 操作的監(jiān)聽
- -(void (^)(void))completionBlock;
- -(void)setCompletionBlock:(void (^)(void))block;
- 當(dāng)要實(shí)現(xiàn)在A操作完成后實(shí)現(xiàn)B操作時(shí)需要監(jiān)聽A操作
- 操作的依賴
-
NSOperation實(shí)現(xiàn)線程間的通信(下載兩張圖片并合成)
- 思路
- 封裝下載圖片1操作download1
- 封裝下載圖片2操作download2
- 封裝合成圖片操作combie(繪圖)
- 創(chuàng)建隊(duì)列
- 設(shè)置操作依賴
- 把操作添加到隊(duì)列中
- 代碼實(shí)現(xiàn)
/** 下載兩張圖片并合成 */ -(void)combieDownloadPicture{ __block UIImage *image1; __block UIImage *image2; // 封裝下載圖片1操作 NSBlockOperation *download1 = [NSBlockOperation blockOperationWithBlock:^{ NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://pic14.nipic.com/20110522/7411759_164157418126_2.jpg"]]; image1 = [UIImage imageWithData:data]; }]; // 封裝下載圖片2操作 NSBlockOperation *download2 = [NSBlockOperation blockOperationWithBlock:^{ NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://pic28.nipic.com/20130402/9252150_190139450381_2.jpg"]]; image2 = [UIImage imageWithData:data]; }]; // 封裝合成圖片操作 NSBlockOperation *combie = [NSBlockOperation blockOperationWithBlock:^{ // 獲取圖形上下文 UIGraphicsBeginImageContext(CGSizeMake(240, 240)); // 畫圖1 [image1 drawInRect:CGRectMake(0, 0, 240, 120)]; // 畫圖2 [image2 drawInRect:CGRectMake(0, 120, 240, 120)]; // 生成圖片 UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); // 關(guān)閉圖形上下文 UIGraphicsEndImageContext(); // 回到主線程刷新UI [[NSOperationQueue mainQueue] addOperationWithBlock:^{ self.imageView.image = image; }]; }]; // 創(chuàng)建隊(duì)列 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 設(shè)置依賴 [combie addDependency:download1]; [combie addDependency:download2]; // 把操作添加到隊(duì)列中 [queue addOperation:download1]; [queue addOperation:download2]; [queue addOperation:combie]; - 思路
}
```