操作隊(duì)列(NSOperation)
操作隊(duì)列的幾種常用方法
1. NSInvocationOperation
-(void)invocationOperationWithQueue
{
//01 創(chuàng)建一個(gè)非主隊(duì)列
NSOperationQueue * queue = [[NSOperationQueue alloc]init];
//02 封裝操作
NSInvocationOperation *op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download) object:nil];
NSInvocationOperation *op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download) object:nil];
NSInvocationOperation *op3 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download) object:nil];
//03 添加操作到隊(duì)列中(內(nèi)部會自動(dòng)調(diào)用start方法)
[queue addOperation:op1];
[queue addOperation:op2];
[queue addOperation:op3];
}
2. NSBlockOperation
-(void)blockOpertionQueue
{
//01 創(chuàng)建隊(duì)列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//02 封裝操作
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"1---%@",[NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"2---%@",[NSThread currentThread]);
}];
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"3---%@",[NSThread currentThread]);
}];
//追加任務(wù)(系統(tǒng)自動(dòng)開啟子線程來執(zhí)行追加的任務(wù))
[op3 addExecutionBlock:^{
NSLog(@"4+++++%@",[NSThread currentThread]);
}];
//03 添加操作到隊(duì)列中
[queue addOperation:op1];
[queue addOperation:op2];
[queue addOperation:op3];
以上的Block方式還有一種簡便的實(shí)現(xiàn)方式:
//1)創(chuàng)建操作 2)把操作添加到隊(duì)列
NSOperationQueue * queue = [[NSOperationQueue alloc]init];
[queue addOperationWithBlock:^{
NSLog(@"5+++++%@",[NSThread currentThread]);
}];
需要注意的是:這種實(shí)現(xiàn)方式雖然簡單,但是無法的到操作對象宪潮。
拓展:
操作隊(duì)列有一個(gè)屬性可以用來設(shè)置最大并發(fā)數(shù),默認(rèn)情況下急黎,這個(gè)數(shù)為-1路操,表示同一時(shí)間可以執(zhí)行的任務(wù)的數(shù)量不受限制:
static const NSInteger NSOperationQueueDefaultMaxConcurrentOperationCount = -1;
當(dāng)然,我們可以手動(dòng)修改這個(gè)屬性的值: queue.maxConcurrentOperationCount = 1;
如果修改成1的話,就表示同一時(shí)間只允許一個(gè)操作執(zhí)行仅偎,也就是我們所說的串行,而在串行情況下雳殊,我們不可以給操作追加任務(wù)橘沥。
操作隊(duì)列中的依賴和監(jiān)聽
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//01 創(chuàng)建隊(duì)列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
NSOperationQueue *queue2 = [[NSOperationQueue alloc]init];
//02 3操作
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"1---%@",[NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"2---%@",[NSThread currentThread]);
}];
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"3---%@",[NSThread currentThread]);
}];
NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"4---%@",[NSThread currentThread]);
}];
NSBlockOperation *op5 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"5++++++++%@",[NSThread currentThread]);
}];
//設(shè)置監(jiān)聽(在任務(wù)4執(zhí)行完畢之后會立即來調(diào)用此方法)
op4.completionBlock = ^{
NSLog(@"任務(wù)執(zhí)行完畢");
};
//設(shè)置依賴,通過設(shè)置依賴能控制操作的執(zhí)行屬性,本程序的操作執(zhí)行順序?yàn)椋?-4-3-2-1
//注意:不能設(shè)置循環(huán)依賴
[op1 addDependency:op2];
[op2 addDependency:op3];
[op3 addDependency:op4];
[op4 addDependency:op5];
//03 添加操作到隊(duì)列
[queue addOperation:op1];
[queue addOperation:op2];
[queue addOperation:op3];
[queue addOperation:op4];
//可以設(shè)置跨隊(duì)列依賴
[queue2 addOperation:op5];
}
操作隊(duì)列線程間的通信
具體細(xì)節(jié)請看注釋夯秃,與前面的通信方式差別不大座咆,代碼如下:
@implementation ViewController
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//創(chuàng)建非主操作隊(duì)列
NSOperationQueue *queue=[[NSOperationQueue alloc]init];
//封裝操作
NSBlockOperation *op1=[NSBlockOperation blockOperationWithBlock:^{
//獲得圖片的URL
NSURL *url=[[NSURL alloc]initWithString:@"http://ww4.sinaimg.cn/bmiddle/695f1cd4jw1f5xetl00loj21y822t7wh.jpg"];
//將圖片的二進(jìn)制數(shù)據(jù)下載到本地
NSData *data=[NSData dataWithContentsOfURL:url];
//根據(jù)圖片的二進(jìn)制數(shù)據(jù)生成一張圖片
UIImage *image=[[UIImage alloc]initWithData:data];
NSLog(@"%@",[NSThread currentThread]);
//操作隊(duì)列線程間的通信方式
[[NSOperationQueue mainQueue]addOperationWithBlock:^{
self.imageV.image=image;
NSLog(@"%@",[NSThread currentThread]);
}];
}];
[queue addOperation:op1];
//添加監(jiān)聽
[op1 addObserver:self forKeyPath:@"isFinished" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL];
}
//監(jiān)聽屬性的改變
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
NSLog(@"%@",change[NSKeyValueChangeOldKey]);
NSLog(@"%@",change[NSKeyValueChangeNewKey]);
}