首页 > 学院 > 开发设计 > 正文

多线程的详细使用

2019-11-09 16:13:34
字体:
来源:转载
供稿:网友

上篇转载的博文有讲解多线程的几种使用,但是NSOperation的介绍不够详细,在此做一下补充。 NSOperation本身是不能直接用来操作的,需要继承NSOperation实现相应的方法或者直接使用NSBlockOperation、NSInvocationOperation才能正常使用。下面就分别从自定义、NSBlockOperation、NSInvocationOperation三个方面来讲解: 1、自定义

//// PHOperation.h// OperationTest//// Created by 項普華 on 2017/2/9.// 邮箱: xiangpuhua@126.com// 电话: +86 13316987488// 主页: https://github.com/xphaijj// Copyright © 2017年 項普華. All rights reserved.//#import <Foundation/Foundation.h>typedef void(^DownloadBlock)(id file);@interface PHOperation : NSOperation/** * 线程执行下载任务 * * @param urlString 需要下载的地址 * @param downloadBlock 下载完成的回调 * * @return 当前类的实例 */- (id)initWithDownloadURL:(NSString *)urlString block:(DownloadBlock)downloadBlock;@end//// PHOperation.m// OperationTest//// Created by 項普華 on 2017/2/9.// 邮箱: xiangpuhua@126.com// 电话: +86 13316987488// 主页: https://github.com/xphaijj// Copyright © 2017年 項普華. All rights reserved.//#import "PHOperation.h"@interface PHOperation () {}@PRoperty (nonatomic, strong) NSString *urlStr;@property (nonatomic, copy) DownloadBlock block;@end@implementation PHOperation/** * 线程执行下载任务 * * @param urlString 需要下载的地址 * @param downloadBlock 下载完成的回调 * * @return 当前类的实例 */- (id)initWithDownloadURL:(NSString *)urlString block:(DownloadBlock)downloadBlock { self = [super init]; if (self) { _urlStr = urlString; _block = downloadBlock; } return self;}/** * 自定义main方法执行线程任务 */- (void)main { @try { @autoreleasepool { if (self.isCancelled) { return; } NSURL *url = [NSURL URLWithString:self.urlStr]; NSData *data = [NSData dataWithContentsOfURL:url]; if (self.isCancelled) { url = nil; data = nil; return; } if (self.block) { self.block(data); } } } @catch (NSException *exception) { } @finally { }}@end

同步引用方法如下:

NSLog(@"start"); PHOperation *op = [[PHOperation alloc] initWithDownloadURL:@"https://www.lsd1888.com/res/21/57e77030f3d1d.jpg" block:^(id file) { sleep(4); UIImage *image = [UIImage imageWithData:file]; NSLog(@"%@ %@", image, [NSThread currentThread]); }]; [op start];//执行同步操作 NSLog(@"end");

输出结果: 2017-02-09 12:31:41.320 OperationTest[4553:996304] start 2017-02-09 12:31:45.730 OperationTest[4553:996304] , {320, 353} {number = 1, name = main} 2017-02-09 12:31:45.730 OperationTest[4553:996304] end 由输出结果我们可知,同步引用正常调起。

异步引用方法如下:

NSLog(@"start"); NSOperationQueue *phQueue = [[NSOperationQueue alloc] init]; PHOperation *op = [[PHOperation alloc] initWithDownloadURL:@"https://www.lsd1888.com/res/21/57e77030f3d1d.jpg" block:^(id file) { sleep(4); UIImage *image = [UIImage imageWithData:file]; NSLog(@"%@ %@", image, [NSThread currentThread]); }]; [phQueue addOperation:op];//执行异步操作 NSLog(@"end");

输出结果: 2017-02-09 12:28:57.248 OperationTest[4493:979978] start 2017-02-09 12:28:57.249 OperationTest[4493:979978] end 2017-02-09 12:29:01.601 OperationTest[4493:980384] , {320, 353} {number = 5, name = (null)}

由输出结果我们可知异步引用正常调起。

NSLog(@"start"); PHOperation *op = [[PHOperation alloc] initWithDownloadURL:@"https://www.lsd1888.com/res/21/57e77030f3d1d.jpg" block:^(id file) { sleep(4); UIImage *image = [UIImage imageWithData:file]; NSLog(@"1 %@ %@", image, [NSThread currentThread]); }]; PHOperation *op1 = [[PHOperation alloc] initWithDownloadURL:@"https://www.lsd1888.com/res/21/57e77030f3d1d.jpg" block:^(id file) { sleep(2); UIImage *image = [UIImage imageWithData:file]; NSLog(@"2 %@ %@", image, [NSThread currentThread]); }]; [op start]; [op1 start]; NSLog(@"end");

输出结果: 2017-02-09 13:09:52.308 OperationTest[5420:1208386] start 2017-02-09 13:09:56.622 OperationTest[5420:1208386] 1 , {320, 353} {number = 1, name = main} 2017-02-09 13:09:58.852 OperationTest[5420:1208386] 2 , {320, 353} {number = 1, name = main} 2017-02-09 13:09:58.853 OperationTest[5420:1208386] end 由输出结果可知,op与op1执行了同步。

NSLog(@"start"); NSOperationQueue *queue = [[NSOperationQueue alloc] init]; PHOperation *op = [[PHOperation alloc] initWithDownloadURL:@"https://www.lsd1888.com/res/21/57e77030f3d1d.jpg" block:^(id file) { sleep(4); UIImage *image = [UIImage imageWithData:file]; NSLog(@"1 %@ %@", image, [NSThread currentThread]); }]; PHOperation *op1 = [[PHOperation alloc] initWithDownloadURL:@"https://www.lsd1888.com/res/21/57e77030f3d1d.jpg" block:^(id file) { sleep(2); UIImage *image = [UIImage imageWithData:file]; NSLog(@"2 %@ %@", image, [NSThread currentThread]); }]; [queue addOperation:op]; [queue addOperation:op1]; NSLog(@"end");

输出结果: 2017-02-09 13:13:20.089 OperationTest[5510:1234538] start 2017-02-09 13:13:20.090 OperationTest[5510:1234538] end 2017-02-09 13:13:22.440 OperationTest[5510:1234706] 2 , {320, 353} {number = 5, name = (null)} 2017-02-09 13:13:24.534 OperationTest[5510:1234688] 1 , {320, 353} {number = 6, name = (null)} 由输出结果可知:op与op1之间执行了的是异步。

2、NSBlockOperation

NSLog(@"start"); NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ sleep(4); NSLog(@"op1"); }]; [op1 start];//同步执行 NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"op2"); }]; [op2 start];//同步执行 NSLog(@"end");

输出结果: 2017-02-09 12:46:57.590 OperationTest[4835:1073639] start 2017-02-09 12:47:01.684 OperationTest[4835:1073639] op1 2017-02-09 12:47:01.684 OperationTest[4835:1073639] op2 2017-02-09 12:47:01.685 OperationTest[4835:1073639] end 由输出结果可知,以上方法均同步执行。

NSLog(@"start"); NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ sleep(4); NSLog(@"op1"); }]; [op1 start];//同步执行 NSBlockOperation *op2 = [[NSBlockOperation alloc] init]; [op2 addExecutionBlock:^{//异步操作 sleep(3); NSLog(@"start"); }]; [op2 addExecutionBlock:^{ sleep(1); NSLog(@"middle"); }]; [op2 addExecutionBlock:^{ sleep(2); NSLog(@"end1"); }]; [op2 setCompletionBlock:^{ NSLog(@"op2 done"); }]; [op2 start];//同步执行 NSLog(@"end");

输出结果: 2017-02-09 12:51:41.925 OperationTest[4975:1102448] start 2017-02-09 12:51:45.997 OperationTest[4975:1102448] op1 2017-02-09 12:51:47.072 OperationTest[4975:1102542] middle 2017-02-09 12:51:48.070 OperationTest[4975:1102539] end1 2017-02-09 12:51:49.073 OperationTest[4975:1102448] start 2017-02-09 12:51:49.073 OperationTest[4975:1102448] end 2017-02-09 12:51:49.073 OperationTest[4975:1102539] op2 done 由上述执行结果可知:op1与op2之间同步执行,op2内部是异步执行。

NSLog(@"start"); NSOperationQueue *queueBlock = [[NSOperationQueue alloc] init]; NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ sleep(2); NSLog(@"op1"); }]; NSBlockOperation *op2 = [[NSBlockOperation alloc] init]; [op2 addExecutionBlock:^{//异步操作 sleep(3); NSLog(@"start"); }]; [op2 addExecutionBlock:^{ sleep(1); NSLog(@"middle"); }]; [op2 addExecutionBlock:^{ sleep(2); NSLog(@"end1"); }]; [op2 setCompletionBlock:^{ NSLog(@"op2 done"); }]; [queueBlock addOperation:op1]; [queueBlock addOperation:op2]; NSLog(@"end");

执行结果: 2017-02-09 12:54:27.294 OperationTest[5105:1121668] start 2017-02-09 12:54:27.295 OperationTest[5105:1121668] end 2017-02-09 12:54:28.368 OperationTest[5105:1122096] middle 2017-02-09 12:54:29.368 OperationTest[5105:1122113] op1 2017-02-09 12:54:29.369 OperationTest[5105:1122086] end1 2017-02-09 12:54:30.370 OperationTest[5105:1122090] start 2017-02-09 12:54:30.370 OperationTest[5105:1122113] op2 done 由输出结果可知:op1与op2之间异步执行,op2内部异步执行。

3、NSInvocationOperation

NSLog(@"start"); NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doPo:) object:@"1"]; NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doPo:) object:@"2"]; [operation start]; [operation2 start]; NSLog(@"end");

输出结果: 2017-02-09 12:58:43.835 OperationTest[5209:1144896] start 2017-02-09 12:58:47.909 OperationTest[5209:1144896] 休眠4s后 输出参数:1 2017-02-09 12:58:51.984 OperationTest[5209:1144896] 休眠4s后 输出参数:2 2017-02-09 12:58:51.985 OperationTest[5209:1144896] end 根据输出结果可知,operation与operation2同步执行。

NSLog(@"start"); NSOperationQueue *queue = [[NSOperationQueue alloc] init];//直接是异步操作 NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doPo:) object:@"4"]; NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doPo:) object:@"3"]; [queue addOperation:operation]; [queue addOperation:operation2]; NSLog(@"end");

输出结果: 2017-02-09 13:01:19.211 OperationTest[5275:1160990] start 2017-02-09 13:01:19.213 OperationTest[5275:1160990] end 2017-02-09 13:01:22.287 OperationTest[5275:1161244] 休眠3s后 输出参数:3 2017-02-09 13:01:23.288 OperationTest[5275:1161249] 休眠4s后 输出参数:4 根据输出结果可知:operation与operation2之间异步执行。

综上所述:实现NSOperation的子类,实例本身调用start方法即执行同步方法,而加入执行队列以后执行异步方法。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表