04 多线程
来源:互联网 发布:高德软件股票行情 编辑:程序博客网 时间:2024/04/30 13:53
1.多线程的基本概念
每一个程序都有一个主线程,程序启动时创建(调用main来启动)
主线程的生命周期是和应用程序绑定的,程序结束时,主线程也就停止
多线程技术表示,一个应用程序有多个线程,使用多线程能提供cup的使用率,防止主线程阻塞
任何有可能堵塞主线程的任务不要在主线程执行(访问网络)
注意:
线程使用不是无节制的
只有主线程有直接修改UI的能力(子线程与主线程通信)
2.多线程技术
3.线程的创建与启动
01.NSThread:
- (void)viewDidLoad { [super viewDidLoad]; // 开启了一个子线程,主线程继续执行,子线程也继续执行 // 1、[NSThread detachNewThreadSelector:@selector(test1) toTarget:self withObject:nil]; // 2、alloc 创建线程需要手动开启 /* NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(test1) object:nil]; // 手动开启线程 [thread start]; [self test2]; */ // 3、设置图片 imgView = [[UIImageView alloc] initWithFrame:CGRectMake(60, 100, 200, 200)]; imgView.backgroundColor = [UIColor redColor]; [self.view addSubview:imgView]; NSLog(@"current Thread : %@", [NSThread currentThread]);}- (void)refreshUI:(UIImage *)image{ imgView.image = image;}#pragma mark - 设置图片- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ //[NSThread detachNewThreadSelector:@selector(subThread:) toTarget:self withObject:@(2)]; // 开启后台线程(子线程) [self performSelectorInBackground:@selector(subThread:) withObject:nil];}- (void)subThread:(NSNumber *)number{ // ARC // 因为在子线程创建的自动释放的对象,是不能够入主线程的自动释放中的 @autoreleasepool { NSLog(@"current Thread : %@", [NSThread currentThread]); // 耗时操作 NSURL *url = [NSURL URLWithString:@"http://f.hiphotos.baidu.com/image/w%3D2048/sign=110ed40be9f81a4c2632ebc9e3126159/b3b7d0a20cf431add6d225464936acaf2edd9848.jpg"]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:data]; // 刷新UI 错误了!不能在子线程中刷新UI的事情,很有可能会崩溃 //imgView.image = image; // 只能在主线程做刷新UI,涉及到主线程和子线程通信(NSObject中方法) /** * 从子线程回到主线程 * (1)回到主线程的方法 * (2)传递的参数可以为空 * (3)YES,必须等待主线程refreshUI: NO,不需要等待 */ [self performSelectorOnMainThread:@selector(refreshUI:) withObject:image waitUntilDone:YES]; // 假设子线程还有若干事情 // YES,必须走完refreshUI: // NO,主线程继续执行,子线程也接着执行 }}#pragma mark - 开启了线程了,打印交替进行了(2条执行路径)- (void)test1{ for (int i = 0; i < 1000; i++) { // 性能开销比较大 NSLog(@"task 1: %d", i); }}- (void)test2{ for (int i = 0; i < 100; i++) { // 性能开销比较大 NSLog(@"task 2: %d", i); }}#pragma mark - NSLog 性能开销比较大- (IBAction)task1:(UIButton *)sender { for (int i = 0; i < 10000; i++) { // 性能开销比较大 //NSLog(@"task 1: %d", i); } //NSLog(@"task 1");}- (IBAction)task2:(UIButton *)sender { for (int i = 0; i < 100000; i++) { } //NSLog(@"task 2"); }
NSThread的常用方法:
//获取当前线程对象+ (NSThread *)currentThread;//使当前线程睡眠指定的时间,单位为秒+ (void)sleepForTimeInterval:(NSTimeInterval)ti;//退出当前线程+ (void)exit;//判断当前线程是否为主线程+ (BOOL)isMainThread//启动该线程- (void)start
// 如果我们DEBUG模式【调试】(RELEASE模式【发布】)/** * 源代码 * 编译(目标代码).o / Debug 系统库文件(冗余,多) * 链接(多个文件,用户定义文件,系统库文件) * \ Release 系统库文件(少) */#ifdef DEBUG #define MYLog(...) NSLog(__VA_ARGS__)#else #define MYLog(...)#endif
02.NSOperation
@interface ViewController (){ NSOperationQueue *queue;}@end@implementation ViewController/** * 阻塞主线程 - 耗时的操作 */- (void)viewDidLoad { [super viewDidLoad]; // 同步:先做A【耗时操作、界面卡顿】,再去做B // 异步:同时进行A、B和操作 // 1 同步操作 /* NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(op1) object:nil]; // 开启了操作,调用指定的方法 [op1 start]; */ // NSOperation 抽象类,不实例化 /** * (1) NSInvocationOperation * (2) NSBlockOperation */ // 2 异步操作 NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(op1) object:nil]; // 设置优先级 [op1 setQueuePriority:NSOperationQueuePriorityVeryLow]; NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(op2) object:nil]; [op2 setQueuePriority:NSOperationQueuePriorityVeryHigh]; // 当子线程完成时 [op2 setCompletionBlock:^{ // NSLog(@"YES : %@", [NSThread currentThread]); }]; NSInvocationOperation *op3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(op3) object:nil]; [op3 setQueuePriority:NSOperationQueuePriorityLow]; NSInvocationOperation *op4 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(op4) object:nil]; [op4 setQueuePriority:NSOperationQueuePriorityNormal]; NSBlockOperation *op5 = [NSBlockOperation blockOperationWithBlock:^{ //NSLog(@"op2 : %@", [NSThread currentThread]); for (int i = 0; i < 10; i++) { NSLog(@"block op5 is :%d", i); } }]; [op5 setQueuePriority:NSOperationQueuePriorityHigh]; // 一旦将操作对象放入“操作队列”中,这个操作就变了异步操作(开启一个线程) // 此外,我们不需要将“操作”对象手动开启,当这个操作加入到“队列”中,事情开始了 queue = [[NSOperationQueue alloc] init]; // 设置队列的并发数 [queue setMaxConcurrentOperationCount:1]; //[queue addOperation:op1]; //[queue addOperation:op2]; //[queue addOperation:op3]; //[queue addOperation:op4]; //[queue addOperation:op5]; NSArray *ops = @[op1, op2, op3, op4, op5]; // YES 阻塞当前线程(主线程),必须等待所有“操作队列”结束之后 // NO 不会阻塞主线程 [queue addOperations:ops waitUntilFinished:NO]; // 3 设置依赖关系 /* NSBlockOperation *op7 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"hello op7"); }]; NSBlockOperation *op8 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"hello op8"); // 根据栏目ID,请求具体内容 }]; NSBlockOperation *op9 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"hello op9"); // 先请求栏目数据 NSArray【model】 }]; // 设置依赖关系,切记不要“循环依赖” 得出op9 op8 op7 [op7 addDependency:op8]; [op8 addDependency:op9]; queue = [[NSOperationQueue alloc] init]; [queue addOperations:@[op7, op8, op9] waitUntilFinished:NO]; */}- (void)op1{ //NSLog(@"op1 : %@", [NSThread currentThread]); for (int i = 0; i < 10; i++) { NSLog(@"op1 is : %d", i); } //子线程与主线程之间通信 //[self performSelectorOnMainThread:@selector(test) withObject:nil waitUntilDone:YES]; // 回到主线程 [[NSOperationQueue mainQueue] addOperationWithBlock:^{ NSLog(@"hello %@", [NSThread currentThread]); }];}- (void)op2{ for (int i = 0; i < 10; i++) { NSLog(@"op2 is : %d", i); }}- (void)op3{ for (int i = 0; i < 10; i++) { NSLog(@"op3 is : %d", i); }}- (void)op4{ for (int i = 0; i < 10; i++) { NSLog(@"op4 is : %d", i); }}
同步是无法取消的。
还学了线程锁:
// synchronized 锁的作用 /* @synchronized(self) { if (_allTickts > 0) { // 线程睡眠(测试) [NSThread sleepForTimeInterval:2]; _allTickts--; NSLog(@"_allTickts : %d", _allTickts); }else { NSLog(@"票已经卖了"); } }*/ // NSLock /* [_lock lock];
03.GCD
- (void)viewDidLoad { [super viewDidLoad]; //[self gcd1]; //[self gcd2]; [self gcd3];}- (void)gcd3{ dispatch_group_t group = dispatch_group_create(); dispatch_queue_t queue = dispatch_queue_create("com.wxhl.c", DISPATCH_QUEUE_CONCURRENT); dispatch_group_async(group, queue, ^{ NSLog(@"t 1: %@", [NSThread currentThread]); for (int i = 0; i < 20; i++) { NSLog(@"t 1 : %d", i); } }); dispatch_group_async(group, queue, ^{ NSLog(@"t 2: %@", [NSThread currentThread]); for (int i = 0; i < 20; i++) { NSLog(@"t 2 : %d", i); } }); dispatch_group_notify(group, queue, ^{ NSLog(@"finish : %@", [NSThread currentThread]); }); dispatch_group_t group1 = dispatch_group_create(); dispatch_queue_t queue1 = dispatch_queue_create("com.wxhl.c", DISPATCH_QUEUE_CONCURRENT); dispatch_group_async(group1, queue1, ^{ NSLog(@"g 1: %@", [NSThread currentThread]); for (int i = 0; i < 100; i++) { NSLog(@"g 1 : %d", i); } }); dispatch_group_notify(group1, queue1, ^{ NSLog(@"finish"); });}- (void)gcd2{ // 死锁问题 // 串行队列 dispatch_queue_t queue = dispatch_get_main_queue(); // 主队列 dispatch_sync(queue, ^{ NSLog(@"sync1 : %@", [NSThread currentThread]); });}- (void)gcd1{ /** * (1) 队列的名字 "com.wxhl.q" * (2) 队列的属性 a. DISPATCH_QUEUE_CONCURRENT (并发队列(global_queue),并发线程队列) b. DISPATCH_QUEUE_SERIAL (串行队列 只会创建一个子线程,顺序执行(依赖)) c. dispatch_get_main_queue 主队列 * (3) 是否开辟子线程,看对队列,和异步和同步无关,如果是主队列,在主线程中,其他队列都是创建了子线程 */ dispatch_queue_t queue = dispatch_queue_create("com.wxhl.q", DISPATCH_QUEUE_CONCURRENT); /** * 队列的优先级 */ //dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(queue, ^{ NSLog(@"t 1 : %@", [NSThread currentThread]); for (int i = 0; i < 20; i++) { NSLog(@"t 1 : %d", i); } /* // 同步 dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"%@", [NSThread currentThread]); });*/ // 异步(请参考 waitUntilDone:YES理解) dispatch_async(dispatch_get_main_queue(), ^{ //NSLog(@"%@", [NSThread currentThread]); }); }); dispatch_async(queue, ^{ NSLog(@"t 2 : %@", [NSThread currentThread]); for (int i = 0; i < 20; i++) { NSLog(@"t 2 : %d", i); } }); dispatch_async(queue, ^{ NSLog(@"t 3 : %@", [NSThread currentThread]); for (int i = 0; i < 20; i++) { NSLog(@"t 3 : %d", i); } }); //[NSThread detachNewThreadSelector:@selector(test1) toTarget:self withObject:nil];}- (void)test1{ // ..... [self performSelectorOnMainThread:@selector(refreshUI) withObject:nil waitUntilDone:YES]; // .....}- (void)refreshUI{ }
0 0
- 04 多线程
- 01-04多线程记要
- 多线程11天--04
- 多线程12天--04
- 07---多线程04
- 04、J2SE基础-多线程
- 04_多线程
- Python 多线程学习04
- Java基础04多线程
- 04wxWidgets多线程
- 2017.12.04 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- C#操作sql通用类 SQLHelper
- Apache服务器的启动以及 403 forbidden 问题的解决
- java 容器深入研究之使用Abstract类定制
- 查找maven中的groupId,artifactId,version等信息的方式
- Servlet 3.0 新特性详解(五)ServletContext 的性能增强及HttpServletRequest 对文件上传的支持
- 04 多线程
- 博客园学习网站
- cocos2dx 点击事件分析(1)
- C语言中函数的思考(可以返回局部变量吗)
- 郝斌数据结构教学视频下载地址
- iOS应用安全Part4:使用Cycript进行运行时分析
- 深入解读Tomcat(四)
- 第三周项目5-5:多文件组织
- KVC 和 KVO 的一点理解