一、进程与线程
1、进程:每个应用程序就是一个进程,每个进程都是相互独立存在的。
2、线程:当一个进程要执行任务的时候,就必须需要线程,也就是说,进程的所有任务都是在线程中执行的,每个进程至少有一个线程(主线程),各线程之间互不干扰。主线程负责执行程序的所有代码,这些代码只能顺序执行,无法并发执行。
3、一个进程是有一个或多个线程所组成的。进程只负责资源的调度和分配,线程才是程序真正的执行单元,负责代码的执行。
二、单线程与多线程
1、单线程:只有一个主线程的叫做单线程。
2、多线程:1个进程中可以开启多条线程,每条线程可以并行(同时)执行不同的任务,例如:进程 ->车间,线程->车间工人。多线程技术可以提高程序的执行效率。
3、什么时候使用多线程:(1)、大量运算(for循环便利多次的时候)
(2)、数据读取(本地),数据查询所有数据的时候
(3)、网络请求(同步网络请求)
4、单、多线程的区别:单线程:只有一个线程,代码顺序执行,容易出现代码阻塞现象(页面假死)。
多线程:有多个线程,线程间独立运行,能有效地避免代码阻塞现象,提高程序的运行效率
三、iOS多线程实现种类
声明:所有运行多线程的地方都要加自动释放池,程序开始执行的时候,系统会给主线程自动添加一个自动释放池,手动给子线程添加的自动释放池,要手动释放。
1、NsThread ,一个轻量级的多线程
- (void)thread
{
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(calculator) object:nil];
[thread start];
[thread release];
[NSThread detachNewThreadSelector:@selector(calculator) toTarget:self withObject:nil];
}
- (void)calculator
{
@autoreleasepool {
NSInteger number = 0;
for (NSInteger i = 0; i <= 10; i++) {
number += i;
NSLog(@"%ld", number);
}
}
2、NSObject,存在一个最简单的后台执行方法
[self performSelectorInBackground:@selector(calculator) withObject:nil];
3、NSOperation和NSOperationQueue
不直接创建NSOperation的对象,用继承,自定义Operation
NSLog(@"main thread");
MyOperation *operation = [[MyOperation alloc] init];
调用start运行main
[operation start];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue setMaxConcurrentOperationCount:1];
最大并发数是1的时候, 线程与线程之间是同步(serial)的,也就是一个线程执行结束后,第二个线程再执行
[queue addOperation:operation];
把operation放入queue里,就不用调用start方法,queue会自行调用,在子线程中运行,与主线程号不再一样
线程并发(concurrent), 互不干扰同时进行, iOS线程数<=10
可以通过@property NSInteger maxConcurrentOperationCount;来控制最大线程数
MyOperation *op = [[MyOperation alloc] init];
[queue addOperation:op];
[op release];
[operation release];
[queue release];
block里面的内容就是对县城所要执行的代码
NSBlockOperation *ope = [NSBlockOperation blockOperationWithBlock:^{
@autoreleasepool {
for (int i = 0; i <= 10; i++) {
NSLog(@"%d", i);
}
}
}];
NSOperationQueue *qu = [[NSOperationQueue alloc] init];
[qu addOperation:ope];
[qu release];
NSInvocationOperation *inv = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(calculator) object:nil];
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[queue addOperation:inv];
[queue release];
[self creatSetialGCD];
[self creatConcurrentGCD];
4、GCD多线程
- (void)creatSetialGCD
{
第一步 : 创建一个同步线程队列,"first"相当于线程的名字,后面的是把它定义为同步(serial)
dispatch_queue_t queue = dispatch_queue_create("first", DISPATCH_QUEUE_SERIAL);
第二步 : 异步执行同步线程队列,把block的内容放到线程队列里,然后异步async执行同步queue(与主线程是异步的)
dispatch_async(queue, ^{
写多线程的代码
GCD里面没有自从释放池
所有的子线程都不能修改UI,只能在主线程修改
下载一张图片并显示到界面上,用同步下载
NSString *path = [NSString stringWithFormat:@"http://a.hiphotos.baidu.com/image/pic/item/a9d3fd1f4134970a10b9b62297cad1c8a6865df0.jpg"];
NSString *urlStr = path;
NSURL *url = [NSURL URLWithString:urlStr];
NSMutableURLRequest *requeset = [NSMutableURLRequest requestWithURL:url];
[requeset setHTTPMethod:@"GET"];
NSURLResponse *responce = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:requeset returningResponse:&responce error:&error];
UIImage *aImage = [UIImage imageWithData:data];
显示到界面上,所有的UI相关的内容全部要在主线程上运行
返回主线程,block内的语句在主线程上运行
dispatch_async(dispatch_get_main_queue(), ^{
UIImageView *image = [[UIImageView alloc] initWithImage:aImage];
[image setFrame:CGRectMake(20, 200, 200, 300)];
[self.view addSubview:image];
[image release];
});
});
}
- (void)creatConcurrentGCD用的最多,并发GCD
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL *url = [NSURL URLWithString:@"http://img.hb.aicdn.com/38a96fef870fc497a963e59ee63a46cb293e7873921a-Yfk1ko_fw658"];
同步下载
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *aImage = [UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
UIImageView *image = [[UIImageView alloc] initWithImage:aImage];
[image setFrame:CGRectMake(20, 200, 245, 300)];
[self.view addSubview:image];
[image release];
});
});
}