iOS 多线程

起标题要低调点,不喜欢那种用标题来骗小伙伴进来刷流量,默默的走心就好了。喜欢的小伙伴点个喜欢哦。。。

对比

一、pthread (了解)

#import <pthread.h>
// 创建
pthread_t thread;
pthread_create(&thread, NULL, run, NULL);

void * run(void *param)
{
    // 耗时操作
    return NULL;
}

二、NSThread(掌握)

// 创建1.
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"jack"];

thread.name = @"my-thread";

[thread start];

// 创建2.
[NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"rose"];

// 创建3.
[self performSelectorInBackground:@selector(run:) withObject:@"jack"];

// 耗时操作
- (void)run:(NSString *)param
{
}
// 其他
[NSThread sleepForTimeInterval:2]; // 让线程睡眠2秒(阻塞2秒)
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]];
[NSThread sleepUntilDate:[NSDate distantFuture]];// 睡到死。。
[NSThread exit]; // 直接退出线程
[NSThread currentThread]; // 当前线程
[NSThread mainThread]; // 主线程
// 加锁 ,互斥锁,缺点需要消耗大量的CPU资源
// 线程同步
@synchronized(self) {
 // 需要锁定的代码
}
// 延迟执行
[self performSelector:<#(nonnull SEL)#> withObject:nil afterDelay:<#(NSTimeInterval)#>];

// 线程通讯

// 回到主线程,显示图片
[self.imageView performSelector:@selector(setImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:NO];
[self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];

[self performSelectorOnMainThread:@selector(showImage:) withObject:image waitUntilDone:YES];// YES 是等完事,向下走 NO就是不等,直接走

- (void)showImage:(UIImage *)image
{
    self.imageView.image = image;
}

三、GCD(掌握)

对比
// 创建并发队列
dispatch_queue_t queue = dispatch_queue_create("com.yzgcode.queue", DISPATCH_QUEUE_CONCURRENT);
// 创建串行队列
dispatch_queue_t queue = dispatch_queue_create("com.yzgcode.queue", DISPATCH_QUEUE_SERIAL);// 第二个参数为NULL也可
// 获得全局并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 获得主队列, 使用的时候注意点,别玩死就OK
dispatch_queue_t queue = dispatch_get_main_queue();

// 其他

// 获取当前队列的名字
dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)

// 不能是全局的,然后会分开(自己领会吧。。)
dispatch_barrier_async(<#dispatch_queue_t queue#>, <#^(void)block#>)

// 延迟
// 在x秒后把任务追加到队列中,并不是在x秒后执行
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
    });

// 快速遍历
dispatch_apply 将外面的线程(main线程)阻塞了, 他会等待其他所有的循环运行完毕才会往下执行
dispatch_apply(3, queue, ^(size_t index) {
        NSLog(@"apply loop: %zu, %@", index, [NSThread currentThread]);
    });

// 队列组
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(group, queue, ^{
});
dispatch_group_async(group, queue, ^{        
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
});


// 优先级
dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("com.yzgcode.queue", NULL);
dispatch_queue_t globalDispatchQueueBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_set_target_queue(mySerialDispatchQueue, globalDispatchQueueBackground);
上面的代码,dispatch_set_target方法的第一个参数是要设置优先级的队列,第二队参数是则是参考的的队列,使第一个参数与第二个参数具有相同的优先级。

dispatch_suspend 挂起指定的队列
dispatch_supend(queue);
dispatch_resume 恢复指定队列
dispatch_resume(queue);
线程挂起对已执行的任务没有影响,挂起后,还未执行的任务停止执行,待恢复后,这些任务继续执行

Dispatch Semaphore(信号量)
信号量持有计数信号,如果信号量计数大于或等于1,那么允许线程执行,否则线程将阻塞
// 创建信号量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1); // 1 表示信号量计数初始值
发出等待信号(信号量计数减1)
dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER);
发出通行信号 (信号量计数加1)
dispatch_semaphore_signal(_semaphore);
例:
- (IBAction)createSemaphore:(id)sender { 
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
  _semaphore = dispatch_semaphore_create(0); //创建一个计数为零的信号量  
  for (int a = 0 ; a<10 ;a ++) { //向队列添加个任务 dispatch_async(queue, ^{ 
      dispatch_semaphore_wait(_semaphore,  DISPATCH_TIME_FOREVER); //进来信号量减1,当它为零的时候不会再减变为负数 
          NSLog(@"%i",a); 
      }); 
  }
}
- (IBAction)semaphorePlusOne:(id)sender { 
  //信号量加1 
  dispatch_semaphore_signal(_semaphore);
}
1、第一个函数创建了计数量为零的信号量。当所有的任务,跑到dispatch_semaphore_wait这个方法的时候,因为信号量当前计数为0,那么它们只能阻塞在这里了。
2、执行第二个方法,给信号量加1,那么在上面阻塞的任务抽出一个执行。

四、NSOperation

4.1基本使用

NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
        // 在主线程
       NSLog(@"下载1------%@", [NSThread currentThread]);
}];
    // 添加额外的任务(在子线程执行)
[op addExecutionBlock:^{
        NSLog(@"下载2------%@", [NSThread currentThread]);
}];

[op addExecutionBlock:^{
        NSLog(@"下载3------%@", [NSThread currentThread]);
}];
[op addExecutionBlock:^{
        NSLog(@"下载4------%@", [NSThread currentThread]);
}];
    
[op start];



 // 创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    // 创建操作(任务)
    // 创建NSInvocationOperation
    NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download1) object:nil];
    NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download2) object:nil];
    
    // 创建NSBlockOperation
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download3 --- %@", [NSThread currentThread]);
    }];
    
    [op3 addExecutionBlock:^{
        NSLog(@"download4 --- %@", [NSThread currentThread]);
    }];
    [op3 addExecutionBlock:^{
        NSLog(@"download5 --- %@", [NSThread currentThread]);
    }];
    
    
    NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download6 --- %@", [NSThread currentThread]);
    }];
    
    // 创建YZGOperation // 自定义Operation,重写main方法
    // 在耗时操作的时候加判断 if(self.isCancelled) return;
    YZGOperation *op5 = [[YZGOperation alloc] init];
    
    // 添加任务到队列中
    [queue addOperation:op1]; // [op1 start]
    [queue addOperation:op2]; // [op2 start]
    [queue addOperation:op3]; // [op3 start]
    [queue addOperation:op4]; // [op4 start]
    [queue addOperation:op5]; // [op5 start]


- (void)download1
{
    NSLog(@"download1 --- %@", [NSThread currentThread]);
}

- (void)download2
{
    NSLog(@"download2 --- %@", [NSThread currentThread]);
}

4.2简单方法

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperationWithBlock:^{
        NSLog(@"download1 --- %@", [NSThread currentThread]);
 }];

4.3 一些属性

// 创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];  
// 设置最大并发操作数
queue.maxConcurrentOperationCount = 1; // 就变成了串行队列
queue.suspended = YES;// 暂停执行
[queue cancelAllOperations]; // 取消

4.4依赖

类似于GCD 队列组

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download1----%@", [NSThread  currentThread]);
    }];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download2----%@", [NSThread  currentThread]);
    }];
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download3----%@", [NSThread  currentThread]);
    }];
    NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
        for (NSInteger i = 0; i<10; i++) {
            NSLog(@"download4----%@", [NSThread  currentThread]);
        }
    }];
    NSBlockOperation *op5 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download5----%@", [NSThread  currentThread]);
    }];
    op5.completionBlock = ^{
        NSLog(@"op5执行完毕---%@", [NSThread currentThread]);
    };
    
    // 设置依赖
    [op3 addDependency:op1];
    [op3 addDependency:op2];
    [op3 addDependency:op4];
    
    [queue addOperation:op1];
    [queue addOperation:op2];
    [queue addOperation:op3];
    [queue addOperation:op4];
    [queue addOperation:op5];

4.5 线程间通讯

    [[[NSOperationQueue alloc] init] addOperationWithBlock:^{
        // 图片的网络路径
       NSURL *url = [NSURL URLWithString:@"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg"];
 
        // 加载图片
        NSData *data = [NSData dataWithContentsOfURL:url];
        
        // 生成图片
        UIImage *image = [UIImage imageWithData:data];
        
        // 回到主线程
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.imageView.image = image;
        }];
    }];

五、参考

http://www.jianshu.com/p/456672967e75
MJ

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,653评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,321评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,833评论 0 324
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,472评论 1 266
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,306评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,274评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,658评论 3 385
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,335评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,638评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,697评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,454评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,311评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,699评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,986评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,254评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,647评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,847评论 2 335

推荐阅读更多精彩内容

  • 在这篇文章中,我将为你整理一下 iOS 开发中几种多线程方案,以及其使用方法和注意事项。当然也会给出几种多线程的案...
    伯恩的遗产阅读 274,248评论 251 2,331
  • 本文首发于我的个人博客:「程序员充电站」[https://itcharge.cn]文章链接:「传送门」[https...
    ITCharge阅读 346,745评论 308 1,925
  • 在这篇文章中,我将为你整理一下 iOS 开发中几种多线程方案,以及其使用方法和注意事项。当然也会给出几种多线程的案...
    张战威ican阅读 596评论 0 0
  • 突然想写这么一篇文章是因为我自己就是一个很爱面子的人, 常常被老婆批评, 所以觉得有必要自己辩护一下. 在维基百科...
    DustinTang阅读 746评论 0 2
  • 5月27日的生日花,黄杜鹃。 黄杜鹃,是一种人说似云的植物,在山谷,在山领,都可以枝繁叶茂。花开的时节萌发力强,状...
    冬林探花阅读 1,108评论 0 0