IOS线程的一些总结
主线程的作用 (在主线程中才能设置)
显示/刷新UI界面
处理UI事件(比如点击事件、滚动事件、拖拽事件);
主线程的使用注意
别将比较耗时的操作放到主线程中。
耗时操作会卡住主线程。影响体验。
[NSThread currentThread]获得当前线程。
打印线程。num属性显示有多少条线程。
将耗时操作放在子线程中(后台线程,非主线程);
多线程好处在哪?
在用户点击按钮那一刻就有反应
能同时处理耗时操作和用UI控件的事件。
多线程技术:
1,pthread 一套通用的多线程API(几乎不用)
适用于Unix\Linux\Windows等系统
跨平台\可移植
使用难度大。
需要程序员来管理线程的生命周期。
创建一个线程用
pthread_create(&pthread_t,NULL,(void *)(*)(void *),NULL);即可
2,NSThread 使用OC,(程序员管理)
使用更加面向对象
简单易用,可直接操作线程对象
创建一个线程用 [NSThread alloc] init……
[self start] 开启;
selector(mainThread) 返回主线程;
selector(isMainThread) 是否是主线程;
selector (currentThread); 判断当前线程;
可以设置线程优先级,
优先级越高,CUP的占有率越高。
线程有name属性,可以设置名字。
创建线程第2种方式:
[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
分离一条线程,没有返回值。
创建线程第3种方式。
[self performSelectorInBackground:@selector(run:) withObject:@"abc参数"];
每一个时刻只有一个线程在执行。
[thread start]后进入一个可调度线程池(有机会被调度。状态为就绪或运行);
start
new ----》 就绪 -----》运行
《------
调用了sleep方法或等待同步锁 后就进入 阻塞状态(清出线程池) 条件满足后又回到调度池。
调用stop 线程进入的是dead 死亡状态。再也没有了。
+(void)sleepUntilDate:(NSDate *)date;
+(void) sleepForTimeInterval:(NSTimeInterval)ti;
线程运行完之后就会死亡, 不能能再次调用。
[thread exit]线程退出。
3,GCD C
旨在替代NSThread等线程技术
充分利用设备的多核。(自动)
不用管理线程。
GCD有2个核心概念
任务:执行什么样的操作。
队列:用来存放任务。
GCD的使用就2个步骤。
定制任务
确认想做的事情。
将任务添加到队列中
GCD会自动将队列中的任务取出,放到对应的线程中执行。
任务取出遵循队列的FIFO原则,先进先出。后进后出
调用libdispach库才行
都是懿dispatch开头。
1,用同步的方式来执行任务。(有顺序执行)
dispatch_sync(queue,block);同步执行
queue:队列
block:任务
2,用异步的方式执行任务(在另一条线程中执行)
dispatch_async(queue,block);
GCD队列分2大类;
并发队列;
可以让任务同时执行。
串行队列
用函数给队列赋值任务;
队列分为并行和串行。
函数分为同步和异步。
异步函数加并行队列 == 开一条子线程。
同步:在当前线程中执行任务,不具备开启新线程能力
异步:在新的线程中执行任务,具备开启新线程的能力。
并发和串行决定了任务的执行方式。
并发:多个任务并发执行。 调用dispatch_queue_t queue = dispatch_get_global_queue(优先级,随意值);
添加任务到队列中,执行任务。
串行:一个任务执行完毕后,再执行下一个任务。
serial 英文,连续,串行的意思。。
dispatch_queue_t queue = dispatch_queue_create("com.itheima,queue",队列的类型);
队列名称在调试的时候可以看的到代码在哪个队列里面执行。
调用async函数会开启一个线程,但是如果函数的队列是串行的就不会开更多了。每加一个并行队列开启线程数会加1.
调用sync函数不会开线程。并行和串行队列都一样
MRC里面释放用dispatch_release(queue);
ARC里面不能用,会自动释放。
即使在ARC中
凡是函数名中带有create\copy\new\retain等字眼返回值的,都需要在不使用这个数据的时候进行release(有的话都写一下,报错就不写了)
GCD数据类型则不用,release。
CF(Core foundation)的数据类型在ARC环境下还是得需要再做release;
系统自带的用get ,自己创的用create 。(苹果规范);
主线程队列是不会开新线程的。
别在主线程中用同步函数添加主队列,会形成相互等待,死锁。
用异步函数可以(异步可以延缓执行,同步要马上执行)。
同步会在当前进程中执行,会停下来。异步会自己开一个线程。与当前线程并发执行,(只要队列不是主队列)
iOS常见的延时执行有2种方式;
1,[self performSelector:@selector(run) withObject:nil afterDelay:2.0];
2秒之后调用run方法;
2,GCD方式
dispatch_after();//有个队列参数,表示多少秒后在哪个线程中执行。
//1.声明在哪个队列
dispatch_queue_t queue = dispatch_get_main_queue();
// 2.计算任务执行的时间
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC));
// 3.会在when这个时间点, 执行queue中的任务
dispatch_after(when, queue, ^{ //会另外声明一个队列。
NSLog(@"----run----%@", [NSThread currentThread]);
});
需要整个程序执行过程中只能打印一次时。
static dispatch_once_t onceToken;
可以用 dispatch_once(&onceToken,^{
NSLog(@"--------touchesBegin");
});
队列组,:
有这么一种需求。
等2个线程都执行完之后再到主线程中执行操作。
就可以用队列组把2个线程封装。执行队列组。
创建group//比串行执行要快很多。。。
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, ^{
for (int i=0; i<100; i++) {
NSLog(@"执行线程一:%d",i);
}
});
dispatch_group_async(group, queue, ^{
for (int i=0; i<100; i++) {
NSLog(@"执行线程二:%d",i);
}
});
//线程组执行完成后执行:(重点,没有它,要组也没啥用了)
dispatch_group_notify(group, queue, ^{
NSLog(@"线程组执行完成");
});
//下面是重复执行:10代表重复执行次数。中间是执行队列。index是第几次执行;(注意执行是并发(这是与for循环的区别));
dispatch_apply(10, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index) {
//index表示是第几次执行
NSLog(@"执行第%zu次",index);
});
栅栏barrier ,用来将线程分开,执行完上面的线程到执行它再到执行后面的线程;(有队列queue关键字,所以就是把queue队列的隔开,其它队列可不行,中间执行)
dispatch_barrier_async(queue, ^{
NSLog(@"barrier");
});
4,NSOperation OC
基于GCD
比GCD多了一些简单实用的功能
使用更加面向对带的用get ,自己创的用create 。(苹果规范);
, 配合使用NSOperation NSOperationQueue也能实现多线程编程
,NSOperation和NSOperationQueue 实现多线程的具体步骤
先将需要执行的操作封装到一个NSOperation 对象中。
然后将NSOperation对象添加到NSOperationQueue中
系统会自动将NSOperationQueue中的NSOperation取出来
将取出的NSOperation封装的操作放到一条新线程中执行。
NSOperation是一个抽象类,并不具备封装操作的能力,必须使用它的子类。
使用NSOperation子类的方式有3种。
NSInvocationOperation
NSBlockOperation
自定义的子类继承NSOperation,实现内部相应的方法。
NSInvocationOperation
创建操作对象,封装要执行的任务。
NSInvocationOperation * operation = [ alloc] initwithTarget…… 任务是方法;
可以[operation start]调用,但是这样是会在当前线程中调用,并无啥用,还是得放到方法中去;
NSBlockOperation
使用类方法来声明
NSBlockOperation * operation = [NSBlockOperation blockOperationWithBlock^{ }]; 任务是block ,NSBlockOperation 是block的封装
也可以 直接用start 调用,但也无啥用。
有方法: [operation addExecutionBlock:^{
NSLog(@"%@",[NSThread currentThread]);
}];
只要operation封装的任务大于1,就会异步执行。
调用了addExecutionBlock 的话 operation的任务就有多个。 用start是会多线程执行的。
-(void) invocationOperation
{
}
NSOperatinQueue * queue =[ [NSOperationQueue alloc] init];
[queue addOperation:operation1];
[queue addOperation:operation2];//这样直接就会是异步执行。 (并发有着不确定性。但是概率是会有的)
队列可以设置 最大并发数, queue.maxConcurrentOperationCount = 1; 表示在这个队列中最多同时执行的并发任务数为1;
(不要设置太多,不然可能会卡, 2-3就好,5以内,不然UI会卡);
- (void) cancelAllOperations; 队列的全部线程都停掉
也可以调用NSOperation 的-(void)cancel 方法取消单个操作。
-(void)setSuspended:(BOOL)b;//YES 代表暂停队列。
//(一个比较好的地方是 : cancel代表取消的意思,suspended,表示已经挂起,这些英文记住了用来命名挺好的,看看别人的过去时都是加ed的,就是这么强,所以语法不好的话,多关注ios的命名规则时很好的);
当下载时,同时开启多条子线程,当用户操作UI时会发生卡顿现象,那么我们就可以在用户滚动时挂起队列。不操作时就继续队列/
下载时同时开启多条线程下载会比较快。
有个有趣的地方是 NSOperation 居然也有一个队列优先级, 我了个去, 不愧是GCD的封装啊 ,就是那么强大。
还可以设置依赖。来保证执行的顺序;
[operationB addDependency: operationA]; B依赖A 那么B只能在A之后执行。(灵活应用可以做很多事情。)
A-》B B -》C C—》A
小心相互依赖问题。
可以在不同的queue的NSOperation之间创建依赖关系。但是不能相互依赖。
操作的监听。
operation.completionBlock = ^{
//下载完图片后想做的事情。
};
自定义Operation(继承自Operation)
{
要在operation里面实现 -(void)main{}方法
}
多线程安全隐患:1,一块资源可能会被多个线程共享,也就是多个线程可能会访问同一个资源
比如说多个线程访问同一个对象、同一个变量、同一个文件。
使用线程锁来解决,同一时间只能有一个线程访问。
IOS线程的一些总结的更多相关文章
- IOS 线程处理 子线程
IOS 线程处理 子线程的启动与结束 技术交流新QQ群:414971585 IOS中,如果要在主线程中启动一个子线程,可以又两种方法: [NSThread detachNewThreadSelec ...
- iOS线程之——NSCondition
多线程在各种编程语言中都是难点,很多语言中实现起来很麻烦,objective-c虽然源于c,但其多线程编程却相当简单,可以与java相媲美.这篇文章主要从线程创建与启动.线程的同步与锁.线程的交互.线 ...
- iOS 线程操作库 PromiseKit
iOS 线程操作库 PromiseKit 官网:http://promisekit.org/ github:https://github.com/mxcl/PromiseKit/tree/master ...
- ios线程和GCD
1.什么是进程? 进程是指在系统中正在运行的一个应用程序.比如同时打开QQ.Xcode,系统就会分别启动2个进程.截图 2.什么是线程? 1).一个进程要想执行任务,必须得有线程(每一个进程至少要有一 ...
- iOS - 线程管理
iOS开发多线程篇—GCD的常见用法 一.延迟执行 1.介绍 iOS常见的延时执行有2种方式 (1)调用NSObject的方法 [self performSelector:@selector(run) ...
- iOS 线程锁同步机制
转载自 http://yulingtianxia.com/blog/2015/11/01/More-than-you-want-to-know-about-synchronized/ 如果你已经使用 ...
- IOS线程操作(3)
采用CGD更有效的比前两个(它被认为是如此,有兴趣的同学可以去试试). 这是推荐的方式来使用苹果的比较. GCD它是Grand Central Dispatch缩写,这是一组并行编程C介面. GCD是 ...
- ios线程和GCD和队列同步异步的关系
1.什么是进程? 进程是指在系统中正在运行的一个应用程序.比如同时打开QQ.Xcode,系统就会分别启动2个进程.截图 2.什么是线程? 1).一个进程要想执行任务,必须得有线程(每一个进程至少要有一 ...
- iOS 线程安全--锁
一,前言 线程安全是iOS开发中避免了的话题,随着多线程的使用,对于资源的竞争以及数据的操作都可能存在风险,所以有必要在操作时保证线程安全. 二,为什么要使用锁? 由于一个进程中不可避免的存在多线程, ...
随机推荐
- 封装实现一个自己的tabbar
实现效果:
- FileUploadInterceptor拦截器的笔记
当请求表单中包含一个文件file,FileUploadInterception拦截器会自动应用于这个文件. 表单: <s:form namespace="/xxx" acti ...
- php include require
includ和require都是把其他页面加载当前页面,不过不同的是,require如果没有找到,或者所包含的页面里面有错误就不会往下执行了 <?php include 'form.php'; ...
- spring component-scan filter
(参考的Spring version : 4.1.6.RELEASE) 我们通常会使用component-scan来进行bean的加载,但是它里面的实现机制却是一知半解.根据原码来理解一下,可能会更加 ...
- EditText 自动格式化电话电话号码
需要格式化的格式为:xxx xxxx xxxx 有两种方式:1.为监听当前输入的长度,当长度为第四位,九位的时候,在原内容上追加空格.(from stackOverFlow)2.每次输入后,格式化当前 ...
- Linux 11g rac PSU
PSU补丁:p22191577_112040_Linux-x86-64.zipOPATCH工具:p6880880_112000_LINUX.zip 解压OPATCH工具 覆盖到/u01/11.2.0/ ...
- Spark Streaming、HDFS结合Spark JDBC External DataSouces处理案例
场景:使用Spark Streaming接收HDFS上的文件数据与关系型数据库中的表进行相关的查询操作: 使用技术:Spark Streaming + Spark JDBC External Data ...
- Symfony2 资料篇
http://www.chrisyue.com/symfony2-in-action-day-1.html 由于Symfony2现在还没有很完善的中文文档,所以不想看文档的同学可以直接进行点击上面的链 ...
- 【转】web测试总结
1.字符型输入框: (1)字符型输入框:英文全角.英文半角.数字.空或者空格.特殊字符“~!@#¥%……&*?[]{}”特别要注意单引号和&符号.禁止直接输入特殊字符时,使用“粘贴.拷 ...
- 【T电商2】ftp服务器搭建
一.为什么需要ftp? 分布式环境一般都有一个专门的图片服务器存放图片.我们使用虚拟机搭建一个专门的服务器来存放图片.在此服务器上安装一个nginx来提供http服务,安装一个ftp服务器来提供图片上 ...