多线程
程序启动->main()函数->UIApplicationMain()->…->
- application:didFinshLaunchins
在程序执行过程中启动多线程以及对应的方法。
进程的基本概念:每一个进程都是一个应用程序。都有独立的内存空间,一般来说一个应用程序存在一个进程,但也有多个进程存在的情况。
同一个进程中的线程共享内存中的内存和资源
多线程 的基本概念
·每一个程序都有一个主线程,程序启动时创建(调用main函数来启动);
·主线程的生命周期和应用程序绑定的,程序结束时主线程停止;
·多线程技术表示,一个应用程序有多个线程,使用多线程能够提高CPU的使用率,防止主线程堵塞;
·任何有可能堵塞主线程的任务不要再主线程执行(比如请求网络数据)。
多线程使用注意:
线程的使用不是无节制的
1.IOS中的主线程的堆栈大小为1M;
2.从第二个线程开始都是512K;
3.这些数值不能通过编译器开关或者是API函数更改。
只有主线程有直接修改UI的能力。
[self performSelectorOnMainThread:@selector(setImage:) withObject:img waitUntilDone:NO];
//回到主线程
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"Main - :%@",[NSThread currentThread]);
self.image = img;
});
//
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
//在主线程更新UI
[self setImage:img];
}];
IOS的三种多线程技术
·NSThread每个NSThread对象对应一个线程,量级较轻;
1. NSThread的创建
类方法:+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;
实例方法:- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument
参数解释:selector:线程执行的方法()
target:selector发送消息的对象;
argument:传给target的唯一参数,也可以为nil。
举例 NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(thread:) object:nil];
[thread start];//启动线程
//创建一个线程对象,可以对线程进行配置
[NSThread detachNewThreadSelector:@selector(thread:) toTarget:self withObject:nil];
//创建线程对象,并且启动线程,方法简单,但是无法获取到新创建的线程对象,也就不能对其进行配置。
[self performSelectorInBackground:@selector(thread:) withObject:nil];
//NSObject的类方法
NSThread常用方法:
// 获取当前线程对象
+ (NSThread *)currentThread;
// 使当前线程睡眠指定的时间,单位为秒
+ (void)sleepForTimeInterval:(NSTimeInterval)ti; // 退出当前线程
+ (void)exit;
// 判断当前线程是否为主线程
+ (BOOL)isMainThread
// 启动该线程
- (void)start
下载图片的例子:
#import "CLPViewController.h"
#define kImgUrl @"http://a.hiphotos.baidu.com/image/pic/item/eaf81a4c510fd9f96737fc6e272dd42a2834a491.jpg"
@interface CLPViewController ()
@end
@implementation CLPViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//类方法,直接创建线程并直接运行
// [NSThread detachNewThreadSelector:@selector(doSomeThing:) toTarget:self withObject:nil];
//实例方法,可以对线程对象进行配置,比如优先级,线程名称
// NSThread *t = [[NSThread alloc] initWithTarget:self selector:@selector(doSomeThing:) object:nil];
// t.name = @"thread-01";//设置线程名
// [t setStackSize:HUGE_VALF];//设置堆栈大小。
// [t start];//启动线程
//注意:方法的调用与线程方法的调用
//不显示创建线程的方法。
//NSObject的类方法
[self performSelectorInBackground:@selector(doSomeThing:) withObject:nil];
}
- (void)doSomeThing:(NSString *)string{
// NSLog(@"%f",CACurrentMediaTime());
// NSThread *t = [NSThread currentThread];
// NSLog(@"%@",t.name);
// NSUInteger size = t.stackSize;
// NSLog(@"%lu",(unsigned long)size);
NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:kImgUrl]];
UIImage *image = [UIImage imageWithData:data];
// NSLog(@"%@",string);
if (image != nil) {
// self.view.layer.contents = (id)image.CGImage;这个方法不可取,
// self.view.backgroundColor = [UIColor redColor];
[self performSelectorOnMainThread:@selector(addImage:) withObject:image waitUntilDone:YES];
}
}
- (void)addImage:(UIImage *)image{
self.view.layer.contents = (id)image.CGImage;
}
@end
//Block语法启动一个线程
NSOperationQueue *threadQueue = [[NSOperationQueue alloc] init];
[threadQueue addOperationWithBlock:^{
NSThread *t = [NSThread currentThread];
if (![t isMainThread]) {
NSLog(@"mutaleThread");
}
}];
//NSOperation开启一个线程
NSOperationQueue *threadQueue = [[NSOperationQueue alloc] init];
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(mutaleThread) object:nil];
[threadQueue addOperation:op];
NSRunLoop的基本概念
·RunLoops是线程相关的基础框架的一部分,一个RunLoop就是一个事件处理的循环,用来不停的调度工作以及处理输入事件;
·线程的生命周期存在五个状态:新建、就绪、运行、阻塞、死亡;
· NSRunLoop可以保持一个线程一直为活动状态,不会马上销毁。
GCD简介
Grand Central Dispatch(GCD)是Apple开发的一个多核编程的解决方案,在Mac OS X 10.6雪豹中首次推出,并随后被引用到了IOS4.0中。GCD是一个替代一个诸如NSThread、NSOperationQueue、NSInvocationOperation等技术的一个高效强大的底层技术。
除了代码的平行执行能力,GCD还提供高度集成的时间控制系统。可以设置句柄来响应文件描述、mach ports(mach port用于OS X上的进程间通讯)、进程、计时器、信号、用户生成事件。这些句柄通过GCD来并发执行,
GCD是一项跨时代的技术,纯C语言、但是又溶有面向对象的思想、基于Block、用我们难以置信的简洁的方法实现了极为复杂的多线程编程。
GCD优点:
易用:GCD比之thread更简单易用,基于block的特性使它极为简单地在不同代码作用域之间传递上下文;
效率:GCD被实现的如此清轻量和优雅,使得它在很多地方比之专门创建消耗资源的线程更实用且快速;
性能:GCD自动根据系统负载来增加线程数量,这就减少了上下文切换以及增强了计算效率;
安全:无需加锁或其他同步机制
Dispatch Queue
Dispatch Queue是执行处理的等待队列,通过dispatch_async等函数,按照先进先出(FIFO)循序追加到Queue中处理。
·执行处理时,存在两种dispatch Queue:
1.Serial Dispatch Queue等待现在正在执行的任务处理结束(串行);
2.Concurrent Dispatch Queue不等待现在正在执行的任务处理结束(并行,并发)。
线程安全
线程锁
@synchronized(self){
…
…
}
死锁。
atomic原子性,线程安全,加锁,执行效率会降低。
nonatomic非原子性