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