iOS開發多線程基礎知識 NSOperation

來源:互聯網
上載者:User

標籤:style   class   blog   tar   ext   color   

-------NSOperation簡介----1.NSOperation的作用·配合使用NSOperation和NSOperationQueue也能實現多線程編程 2.NSOperation和NSOperationQueue實現多線程的具體步驟·先將需要執行的操作封裝到一個NSOperation對象中·然後將NSOperation對象添加到NSOperationQueue中·系統會自動將NSOperation中封裝的操作放到一條新線程中執行 ---------NSOperation的子類----3.NSOperation是個抽象類別,並不具備封裝操作的能力,必須使用它的子類 4.使用NSOperation子類的方式有3種·NSInvocationOperation·NSBlockOperation·自訂子類繼承NSOperation,實現內部相應的方法 ------NSInvocationOperation---5.建立NSInvocationOperation對象

- (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;

6.調用start方法開始執行操作

- (void)start;

一旦執行操作,就會調用target的sel方法

7.注意·預設情況下,調用了start方法後並不會開一條新線程去執行操作,而是在當前線程同步執行操作·只有將NSOperation放到一個NSOperationQueue中,才會非同步執行操作  -------NSBlockOperation--8.建立NSBlockOperation對象

+ (id)blockOperationWithBlock:(void (^)(void))block;

9.通過addExecutionBlock:方法添加更多的操作

- (void)addExecutionBlock:(void (^)(void))block;

注意:只要NSBlockOperation封裝的運算元 > 1,就會非同步執行操作

 

-------NSOperationQueue----

10.NSOperationQueue的作用·NSOperation可以調用start方法來執行任務,但預設是同步執行的·如果將NSOperation添加到NSOperationQueue(操作隊列)中,系統會自動非同步執行NSOperation中的操作 11.添加操作到NSOperationQueue中

- (void)addOperation:(NSOperation *)op;

- (void)addOperationWithBlock:(void (^)(void))block;

 

-------最大並發數----

12.什麼是並發數·同時執行的任務數·比如,同時開3個線程執行3個任務,並發數就是3 13.最大並發數的相關方法

- (NSInteger)maxConcurrentOperationCount;

- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;

-----隊列的取消、暫停、恢複------

14.取消隊列的所有操作

- (void)cancelAllOperations;

提示:也可以調用NSOperation的- (void)cancel方法取消單個操作

15.暫停和恢複隊列

- (void)setSuspended:(BOOL)b; // YES代表暫停隊列,NO代表恢複隊列

- (BOOL)isSuspended;

----操作優先順序-----

16.設定NSOperation在queue中的優先順序,可以改變操作的執行順序

- (NSOperationQueuePriority)queuePriority;

- (void)setQueuePriority:(NSOperationQueuePriority)p;

17.優先順序的取值(優先順序越高,越先執行)·NSOperationQueuePriorityVeryLow = -8L,·NSOperationQueuePriorityLow = -4L,·NSOperationQueuePriorityNormal = 0,·NSOperationQueuePriorityHigh = 4,·NSOperationQueuePriorityVeryHigh = 8 ---操作依賴---18.NSOperation之間可以設定依賴來保證執行順序·比如一定要讓操作A執行完後,才能執行操作B,可以這麼寫

[operationB addDependency:operationA]; // 操作B依賴於操作A

19.可以在不同queue的NSOperation之間建立依賴關係

20.注意:不能相互依賴

·比如A依賴B,B依賴A----操作的執行順序---21.對於添加到queue中的operations,它們的執行順序取決於2點·首先依據NSOperation之間的依賴關係·然後依據NSOperation的優先順序 22.因此,總體的執行順序是·先滿足依賴關係·然後再從NSOperation中選擇優先順序最高的那個執行   ---自訂NSOperation---23.自訂NSOperation的步驟很簡單·重寫- (void)main方法,在裡面實現想執行的任務 24.重寫- (void)main方法的注意點·自己建立自動釋放池(因為如果是非同步作業,無法訪問主線程的自動釋放池)·經常通過- (BOOL)isCancelled方法檢測操作是否被取消,對取消做出響應   --------分割線---NSOperation小代碼1,唯寫一個檔案參考下
//  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

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.