- (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;
- (void)start;
一旦执行操作,就会调用target的sel方法
+ (id)blockOperationWithBlock:(void (^)(void))block;
- (void)addExecutionBlock:(void (^)(void))block;
注意:只要NSBlockOperation封装的操作数 > 1,就会异步执行操作
-------NSOperationQueue----
- (void)addOperation:(NSOperation *)op;
- (void)addOperationWithBlock:(void (^)(void))block;
-------最大并发数----
- (NSInteger)maxConcurrentOperationCount;
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;
-----队列的取消、暂停、恢复------
- (void)cancelAllOperations;
提示:也可以调用NSOperation的- (void)cancel方法取消单个操作
- (void)setSuspended:(BOOL)b; // YES代表暂停队列,NO代表恢复队列
- (BOOL)isSuspended;
----操作优先级-----
- (NSOperationQueuePriority)queuePriority;
- (void)setQueuePriority:(NSOperationQueuePriority)p;
[operationB addDependency:operationA]; // 操作B依赖于操作A
19.可以在不同queue的NSOperation之间创建依赖关系
20.注意:不能相互依赖
// DYFViewController.m
// 624-03-NSOperation
//
// Created by dyf on 14-6-24.
// Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved.
//
#import "DYFViewController.h"
@interface DYFViewController ()
@end
@implementation DYFViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self testOperationQueue];
}
- (void)testOperationListen {
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片1111111%@", [NSThread currentThread]);
// 下载图片
}];
operation3.completionBlock = ^{
// 下载完图片后想做的时期
};
// 2.创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation3];
}
- (void)testOperationQueue {
// 1.封装操作
NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil];
NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"1111111%@", [NSThread currentThread]);
}];
[operation3 addExecutionBlock:^{
NSLog(@"222222%@", [NSThread currentThread]);
}];
[operation3 addExecutionBlock:^{
NSLog(@"33333%@", [NSThread currentThread]);
}];
// 2.创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 5以内,2~3为宜
queue.maxConcurrentOperationCount = 2;
#warning 面试题
// 设置操作依赖(一定要在添加到队列中前设置)
[operation2 addDependency:operation1]; // 执行顺序取决于依赖,先执行完operation1再执行operation2
// 注意:不能相互依赖,循环操作
// 3.添加操作到队列中(自动执行操作,自动开启线程)
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
// 取消所有线程
//[queue cancelAllOperations];
// 暂停队列
//[queue setSuspended:YES];
// 设置操作优先级
//operation1.queuePriority = NSOperationQueuePriorityVeryHigh;
}
- (void)testNSBlockOperation {
// 1.创建操作对象,封装要执行的任务
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 11; i++) {
NSLog(@"1111111%@", [NSThread currentThread]);
}
}];
// 任务数在2各以上,就会开线程
[operation addExecutionBlock:^{
for (int i = 0; i < 11; i++) {
NSLog(@"222222%@", [NSThread currentThread]);
}
}];
[operation addExecutionBlock:^{
for (int i = 0; i < 11; i++) {
NSLog(@"33333%@", [NSThread currentThread]);
}
}];
// 2.执行操作
[operation start];
}
- (void)testNSInvocationOperation {
// 1.创建操作对象,封装要执行的任务
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil];
// 2.执行操作(默认情况下,若操作没有放到队列queue中,都是同步执行)
[operation start];
}
- (void)download
{
for (int i = 0; i < 11; i++) {
NSLog(@"download-----%@", [NSThread currentThread]);
}
}
- (void)run
{
for (int i = 0; i < 11; i++) {
NSLog(@"run------%@", [NSThread currentThread]);
}
}
@end
----自定义NSOperation---
// // DYFDownloadOperation.h // 624-05-自定义Operation // // Created by dyf on 14-6-24. // Copyright (c) 2014年 dyf. All rights reserved. // #import <Foundation/Foundation.h> @class DYFDownloadOperation; @protocol DYFDownloadOperationDelegate <NSObject> @optional - (void)downloadOperation:(DYFDownloadOperation *)operation didFinishedDownload:(UIImage *)image; @end @interface DYFDownloadOperation : NSOperation @property (nonatomic, copy) NSString *url; @property (nonatomic, strong) NSIndexPath *indexPath; @property (nonatomic, weak) id<DYFDownloadOperationDelegate> delegate; @end
//
// DYFDownloadOperation.m
// 624-05-自定义Operation
//
// Created by dyf on 14-6-24.
// Copyright (c) 2014年 dyf. All rights reserved.
//
#import "DYFDownloadOperation.h"
@implementation DYFDownloadOperation
/**
* 在main方法中实现具体操作
*/
- (void)main
{
@autoreleasepool {
if (self.isCancelled) return;
NSURL *imaUrl = [NSURL URLWithString:self.url];
if (self.isCancelled) return;
// 下面这行很耗时
NSData *data = [NSData dataWithContentsOfURL:imaUrl];
if (self.isCancelled) return;
UIImage *image = [UIImage imageWithData:data];
if (self.isCancelled) return;
// 返回主线程显示图片
// 通过代理
if ([self.delegate respondsToSelector:@selector(downloadOperation:didFinishedDownload:)]) {
[self.delegate downloadOperation:self didFinishedDownload:image];
}
}
}
@end
具体利用MVC模式创建的文件老生常谈,只来一个Controller.m文件供参考,数据存储存在问题,可以改用SDWebImage框架处理
//
// DYFTableViewController.m
// 624-05-自定义Operation
//
// Created by dyf on 14-6-24.
// Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved.
//
#import "DYFTableViewController.h"
#import "DYFAppModel.h"
#import "DYFDownloadOperation.h"
#warning Dictionary基础知识不太理解,字典的赋值回去看看笔记
@interface DYFTableViewController ()<DYFDownloadOperationDelegate>
@property (nonatomic, strong) NSArray *apps;
@property (nonatomic, strong) NSOperationQueue *queue;
/**
* key:url value:operation对象
*/
@property (nonatomic, strong) NSMutableDictionary *oprations;
/**
* key:url value:image对象
*/
@property (nonatomic, strong) NSMutableDictionary *images;
@end
@implementation DYFTableViewController
#pragma mark - 4个懒加载
- (NSArray *)apps
{
if (!_apps) {
NSString *path = [[NSBundle mainBundle] pathForResource:@"apps" ofType:@"plist"];
NSArray *arrayApps = [NSArray arrayWithContentsOfFile:path];
NSMutableArray *arrayM = [NSMutableArray arrayWithCapacity:arrayApps.count];
for (NSDictionary *dict in arrayApps) {
DYFAppModel *appM = [DYFAppModel appWithDict:dict];
[arrayM addObject:appM];
}
_apps = arrayM;
}
return _apps;
}
- (NSOperationQueue *)queue
{
if (!_queue) {
_queue = [[NSOperationQueue alloc] init];
// 设置最大并发线程数,最多同时下载3张图片
_queue.maxConcurrentOperationCount = 3;
}
return _queue;
}
- (NSMutableDictionary *)oprations
{
if (!_oprations) {
_oprations = [[NSMutableDictionary alloc] init];
}
return _oprations;
}
- (NSMutableDictionary *)images
{
if (!_images) {
_images = [NSMutableDictionary dictionary];
}
return _images;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
#pragma mark - 数据源方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.apps.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 1.创建cell
static NSString *identifier = @"apps";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
}
// 2.设置cell的数据
DYFAppModel *app = self.apps[indexPath.row];
cell.textLabel.text = app.name;
cell.detailTextLabel.text = app.download;
// 重点是如何从网络下载图片传入cell上面
// 每个url对应一个DYFDownloadOperation对象
// 每个url对应一个image对象
UIImage *image = self.images[app.icon];
if (image) {
// 若缓存中存在图片
cell.imageView.image = image;
}else
{
// 若缓存中不存在图片,则图片要从网上下载
// 设置下载前系统刷出的图片
cell.imageView.image = [UIImage imageNamed:@"身份证小"];
// 基础差,下面这行不太理解
DYFDownloadOperation *operation = self.oprations[app.icon];
if (operation) {
// 若正在下载,则不执行其它操作
}else
{
// 若没在下载,则创建开始下载的子线程
DYFDownloadOperation *operation = [[DYFDownloadOperation alloc] init];
operation.url = app.icon;
operation.indexPath = indexPath;
operation.delegate = self;
// 添加任务进队列,异步下载
[self.queue addOperation:operation];
// 基础差,下面这行不太理解
self.oprations[app.icon] = operation;
}
}
// 3.返回cell
return cell;
}
#pragma mark - DYFDownloadOperationDelegate
- (void)downloadOperation:(DYFDownloadOperation *)operation didFinishedDownload:(UIImage *)image
{
// 1.删除执行完毕的下载操作
[self.oprations removeObjectForKey:operation.url];
// 若图片下载好
if (image) {
// 2.将下载好的图片存入缓存
self.images[operation.url] = image;
// 3.刷新这一行cell的数据
[self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationNone];
// 4.将图片存入沙盒
// 4.1图片先转换为2进制数据
NSData *data = UIImagePNGRepresentation(image);
// 4.2设置沙盒路径
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[self.apps[operation.indexPath.row] icon]];
NSLog(@"%@", path);
// 4.3保存data到path中
[data writeToFile:path atomically:YES];
}
}
// 开始拖拽时候暂停队列
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
[self.queue setSuspended:YES];
}
// 停止拖拽的时候重启队列
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
[self.queue setSuspended:NO];
}
@end
iOS开发多线程基础知识 NSOperation,布布扣,bubuko.com
原文:http://www.cnblogs.com/dyf520/p/3807187.html