多线程 Nsthread GCD 和 Nsopration 的用法

一  pthread : 

/*

参数:

1.线程代号的地址

2.线程的属性

3.调用函数的指针

4.传递给函数的参数

返回值:

- 如果是 0, 表示正确

- 如果是非0,表示错误码

void *--(*)--(void *)

返回值--(函数指针)--(参数)

void *  相当于 OC中的id

*/

-(void)pthreadDemo{

pthread_t threadID;

NSString * str = @"hello 老王";

/*

- 在 ARC 开发中, 如果遇到 OC和C 语言中相同数据类型进行转换,需要使用__bridge "桥接"

- 在 MRC 开发中,不需要桥接

在 OC 中,如果是ARC开发,编译器会在编译的时候,自动根据代码结构,添加 retain , release, autorelease

ARC 只负责 OC部分的代码,不负责C的代码. 如果C的代码里面出现了 retain/create/copy 字样的函数,都需要release

*/

int result = pthread_create(&threadID, NULL, &demo, (__bridge void *)(str));

if (result == 0) {

for (int i  = 0; i < 20; i++) {

NSLog(@"OK!");

}

}else{

NSLog(@"error %d",result);

}

}

void * demo(void *param){

NSString * sss = (__bridge NSString *)(param);

NSLog(@"%@---%@",[NSThread currentThread],sss);

return NULL;

}

一  NSThread

oc语言需要程序员手动管理线程

//创建线程 开辟一个子线程 常用创建方法

 1  NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(demo:) object:@"thread"];

//启动线程

[thread start];

//创建以后立即开启

2  [NSThread detachNewThreadSelector:@selector(demo:) toTarget:self withObject:@"Detach"];

//常用的方法

3   [self performSelectorInBackground:@selector(longOperation) withObject:nil];

延时操作

[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];

[NSThread sleepForTimeInterval:2.0];

杀死线程

//一旦强行终止线程,后续的所有的代码都不会执行

//注意:在终止线程之前,应该注意释放之前分配的对象!否则出现内存泄露!

 4  [NSThread exit];


二 优先级属性

/*优先级

* 优先级只能保证 CPU 调度的可能性会高!

* 多线程的目的: 将耗时的操作放在后台,不阻塞主线程和用户的交互!

* 建议: 尽量不要修改 优先级!

* "优先级翻转"

* 在多线程开发中,不要相信你看到的结果!!一定要理性的(冷静)分析!!

*/

t2.threadPriority = 0.1;

三  资源共享

@synchronized

//参数:就是能够加锁的任意 NSOjbect 对象

//局部变量: 每个线程单独拥有的,无法锁住!!

//注意: 锁一定要是所有线程共享的对象!!

@synchronized (<#token#>) {

<#statements#>

//互斥锁 - 保证锁内的代码,同一时间,只有一条线程能够执行!!

//互斥锁它的范围,应该尽量小,锁范围越大,效率越低!

}

三 GCD 相关用法

1. 什么是GCD

全称是Grand Central Dispatch,可译为“牛逼的中枢调度器”

纯C语言,提供了非常多强大的函数

2. GCD的优势

GCD是苹果公司为多核的并行运算提出的解决方案

GCD会自动利用更多的CPU内核(比如双核、四核 为以后苹果公司推出多核提供兼容)

GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)

程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码

3.GCD中有2个核心概念

任务:执行什么操作

队列:用来存放任务

GCD的使用就2个步骤

定制任务

确定想做的事情

将任务添加到队列中

GCD会自动将队列中的任务取出,放到对应的线程中执行

任务的取出遵循队列的FIFO原则:先进先出,后进后出

4 GCD常用方法

1. 延时操作

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

});

2 一次执行操作(设置单列的时候经常用到)

//GCD提供了一个一次执行的机制,不仅能够保证只会被执行一次.而且是线程安全的!

//GCD-Once 内部是会加锁!! 但是 比普通的互斥锁 效率高 100多倍 苹果推荐使用这个

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

});

3 调度组 

//MARK: 调度组

-(void)group1{

//1.队列

dispatch_queue_t q = dispatch_get_global_queue(0, 0);

//2.调度组

dispatch_group_t g = dispatch_group_create();

//3.添加任务,让队列执行,任务执行情况最终通知组

dispatch_group_async(g, q, ^{

NSLog(@"download A %@",[NSThread currentThread]);

});

dispatch_group_async(g, q, ^{

[NSThread sleepForTimeInterval:1.0];

NSLog(@"download B %@",[NSThread currentThread]);

});

dispatch_group_async(g, q, ^{

[NSThread sleepForTimeInterval:0.8];

NSLog(@"download C %@",[NSThread currentThread]);

});

//4. 所有任务执行完毕后,获得通知

//用一个调度组,可以监听全局队列调度的任务,执行完毕之后,在主队列执行最终处理!

//dispatch_group_notify 本身是异步的

dispatch_group_notify(g, dispatch_get_main_queue(), ^{

//更新UI,通知用户

NSLog(@"OK  %@",[NSThread currentThread]);

});

NSLog(@"come here");

}

//MARK: 主队列,同步任务

//阻塞主线程!!

-(void)gcdDemo2{

//1.队列  -> 一启动就有主线程,主队列只需要获取

dispatch_queue_t q = dispatch_get_main_queue();

NSLog(@"这里!!");

//2.同步任务

dispatch_sync(q, ^{

NSLog(@"能来吗?");

});

NSLog(@"come here -- %@",[NSThread currentThread]);

}

5 GCD总结

/**

GCD 核心概念:将任务添加到队列,指定任务执行的方法

- 任务

- 使用block 封装

- block就是一个提前准备好的代码块,在需要的时候执行

- 队列(负责调度任务)

- 串行队列:一个接一个的调度任务

- 并发对象:可以同时调度多个任务

- 执行任务的函数

- 同步执行: 当前指令不完成,就不会执行下一条指令

- 异步执行: 当前执行不完成,同样可以执行下一条指令

小结:

- 开不开线程,取决于同步\异步. 同步,不开!  异步,开!

- 开多少条线程,取决于队列,串行开一条,并发(异步)开多条!

hank:开启子线程只能是异步!!!  线程多开\并发且异步

只要是异步就开启子线程!!!

全局队列 & 并发队列

1. 名称,并发队列有名称,适合大型项目跟踪错误报告!

2. release,在 MRC 开发时,并发队列需要使用 dispatch_release(q);

结论:目前绝大多数软件都会使用全局队列.

全局队列 & 串行队列

全局队列(并发): 并发,能够调度多个线程,执行效率高!!!

- 费电!!

串行队列: 一个接一个,只能开启一条线程,执行效率低!!

- 省电,省钱,省流量

选择的依据: 根据用户的上网方式!!

- WIFI ,可以开多条线程, 6条

- 3G\4G,尽量少开线程,2~3 条

四  NSOperation

特点:   不能直接使用

目的:  定义子类中共有的属性和方法

子类:- NSInvocationOperation    - NSBlockOperation

1.   创建   //    NSInvocationOperation 操作

NSInvocationOperation * op = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downloadImage:) object:@"Hank"];

//start 方法,会在当前线程执行调度方法

//    [op start];

//1.队列

NSOperationQueue * q = [[NSOperationQueue alloc]init];

//2.将操作添加到队列 - 会自动异步执行调度方法

[q addOperation:op];

2.    //NSBlockOperation 所有的代码都写在一起.更加好维护

NSOperationQueue * q = [[NSOperationQueue alloc]init];

NSBlockOperation * op = [NSBlockOperation blockOperationWithBlock:^{

NSLog(@"%@ ---- %d",[NSThread currentThread],i);

}];

[q addOperation:op];

二  线程间的通讯

[self.opQueue addOperationWithBlock:^{

NSLog(@"耗时操作!! %@",[NSThread currentThread]);

//主线程 更新UI ,主队列

[[NSOperationQueue mainQueue] addOperationWithBlock:^{

NSLog(@"UIUIUI --- %@",[NSThread currentThread]);

}];

}];

三  依赖关系

/**

需求:从网上下载视频\完成之后解码\通知用户

*/

//1.下载

NSBlockOperation * op1 = [NSBlockOperation blockOperationWithBlock:^{

[NSThread sleepForTimeInterval:3.0];

NSLog(@"下载  -  %@",[NSThread currentThread]);

}];

//2.解码

NSBlockOperation * op2 = [NSBlockOperation blockOperationWithBlock:^{

[NSThread sleepForTimeInterval:2.0];

NSLog(@"解码  -  %@",[NSThread currentThread]);

}];

//3.通知用户

NSBlockOperation * op3 = [NSBlockOperation blockOperationWithBlock:^{

NSLog(@"通知用户  -  %@",[NSThread currentThread]);

}];

//NSOperation 提供了依赖关系

//NSOperation 的所有的操作都是异步执行的,但是为了建立任务之间的依赖,提供了dependency的功能

//GCD中,通过同步任务来实现,也可以通过串行队列!

[op2 addDependency:op1];//op2 依赖于 op1  == op1 执行完毕 op2 开始执行

[op3 addDependency:op2];

// !!千万注意!!!:  不要循环依赖!!!!,一旦指定了循环依赖,队列就不能执行被循环依赖的操作了!!

//不会造成死锁!  但是 以前的版本 会死锁!!

//    [op1 addDependency:op3];

[self.opQueue addOperations:@[op1,op2] waitUntilFinished:NO];

//主线程通知用户

[[NSOperationQueue mainQueue] addOperation:op3];

NSLog(@"come here");

四  取消线程

//提示: 取消操作,同样不会取消正在执行中的操作

[self.opQueue cancelAllOperations];

五 暂停/恢复线程

//在设置队列的暂停属性时,并不会判断队列中是否有操作!

//如果不希望用户产生困惑,可以提前做判断

//判断队列中当前是否有操作

if (self.opQueue.operationCount == 0){

NSLog(@"没有操作!!!");

return ;

}

if (self.opQueue.isSuspended) {

//在暂停的时候,队列中的操作数,是包含正在执行的操作!!

NSLog(@"继续 %tu",self.opQueue.operationCount);

self.opQueue.suspended = NO;

}else{

//再次继续运行的时候,如果之前执行的操作已经完成,队列中的操作数就只有未调度的了!!

NSLog(@"暂停 %tu",self.opQueue.operationCount);

self.opQueue.suspended = YES;

}

六 最大线程

//设置同时最大并发操作数量

//WIFI: 5~6

//2G/3G/4G: 2~3

self.opQueue.maxConcurrentOperationCount = 2;

//向队列添加任务

//从 iOS 8.0 开始,无论使用GCD 还是 NSOperation, 都会开启很多线程

//在 iOS 7.0 以前,GCD 通常只会开启 5 ~ 6 条线程!

//目前线程数量多说明:

//1.底层的线程池更大了,能够拿到的线程资源更多了!

//2.对控制同时并发的线程数,要求就更高!

GCD和NSOpration的比较

/*

NSOperation 是苹果公司大力推荐的"并发"技术! 开发者已经不需要关心线程以及线程的生命周期!

,而且我们逃离了GCD的 并发还是串行 异步还是同步!

NSOperation 的核心概念: 将"操作" 添加到 "队列"

GCD的核心概念: 将"任务"添加到队列,指定任务的执行函数(方法)

----------------------------------------------------------------------------------

GCD & NSOperation 的对比

GCD 在 iOS 4.0推出的,主要针对多核处理器做了优化的并发技术,是 C 语言!

- 将"任务"[block]"添加到"队列[串行/并发/主队列/全局],并且指定执行任务的函数[同步/异步]

- 线程间的通讯 dispatch_get_main_queue()

- 提供了一些 NSOperation 不具备的功能

- 一次执行(单例设计模式最常用)

- 延迟执行

- 调度组

- 等等...

NSOperation 在 iOS 2.0 推出的!

- 将操作[异步执行的任务] 添加到 队列[并发队列],就会立刻异步执行

- mainQueue

- 提供了一些 GCD 实现起来比较困难的功能

- 最大并发线程数

- 队列的暂停/继续

- 取消所有操作

- 指定操作之间的依赖关系(GCD 同步实现)

----------------------------------------------------------------------------------

NSOperation类是一个抽象类

特点:

- 不能直接使用

目的:

- 定义子类中共有的属性和方法

子类:

- NSInvocationOperation

- NSBlockOperation

*/

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

推荐阅读更多精彩内容