1.多线程的简单认知
1.进程和线程的认知
进程:一个正在运行的程序就是一个进程 一个进程由一个或多个线程组成进程只负责资源的调度分配,线程才是真正的执行单元
线程
//当我们应用程序刚刚运行的时候,系统会自动为我们开放一个线程,这个线程叫做主线程
//子线程:程序员用代码手动开启的线程
//子线程存在的意义:执行耗时操作的任务
//子线程在执行完自己的任务之后会自动销毁
2.创建线程
第一种
-(void)createNSThread
{
//创建一个线程###
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(haoshicaozuo) object:@"123"];
thread.name = @"这是一个线程";
[thread start];
//NSLog(@"%@",thread);
NSLog(@"%@",[NSThread mainThread]);//打印当前应用程序的主线程
NSLog(@"%@",[NSThread currentThread]);//当前线程
NSLog(@"%d",[NSThread isMainThread]); //判断是否为主线程
}
第二种
-(void)createNSThread1
{
//快捷创建 无返回值
[NSThread detachNewThreadSelector:@selector(haoshicaozuo) toTarget:self withObject:@"456"];
}
第三种
-(void)createNSThread2
{
//隐式开启线程
[NSThread cancelPreviousPerformRequestsWithTarget:self selector:@selector(haoshicaozuo) object:@"789"];
}
2.NSOperation
/NSOperation 是一个抽象类,我们一般不直接使用它,而是使用它的子类NSInvocationOperation 类 还有NSBlockOperation
//如果他们单独使用都是在主线程执行,只有和队列放在一起才是在子线程下执行的
-(void)createNSOperation
{
NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationAction1) object:nil];
//[operation1 start];
NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationAction2) object:
nil];
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 20 ; i < 30 ; i++) {
NSLog(@"%d",i);
}}];
//操作队列
//目的:是将我们的任务放在一个队列中执行
//任务:任务执行在主线程还是在子线程全都是由我们的队列来决定的
//加入到队列
//mainQueue 代表主队列
//如果 alloc init 的就代表其他队列
// NSOperationQueue *queue = [NSOperationQueue mainQueue];
NSOperationQueue *queue = [[NSOperationQueue alloc] init] ;
//先加的先执行,后加的后执行,但执行的时间不一定 可能后边的现执行完
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
}
-(void)operationAction2
{
NSLog(@"%d",[NSThread isMainThread]);
}
-(void)operationAction1
{
NSLog(@"%d",[NSThread isMainThread]);
}
3.GCD
在了解GCD之前我们应该先了解几个基础概念
异步:不再一个线程执行
同步:在同一个线程执行
串行:按顺序串在一起执行
并行:一起执行
#pragma --------- 同步主队列 ------------
//同步不能加主队列 所以这个是错的,仅仅是看个模式
-(void)createScyMain
{
//获得主队列(主队列也是一个串行队列)
dispatch_queue_t queue = dispatch_get_main_queue();
//将任务加到队列中
//第一个参数:放队列的
//第二个参数:要执行的任务
dispatch_sync(queue, ^{
NSLog(@"1.......%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"2.......%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"3.......%@",[NSThread currentThread]);
});
}
#pragma --------- 异步主队列 ------------
//不开辟线程,就在主线程执行
-(void)createAsycnMain
{
//获得主队列(主队列也是一个串行队列)
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
NSLog(@"1..........%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"2..........%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"3..........%@",[NSThread currentThread]);
});
}
#pragma --------- 同步串行队列 ------------
//不具备开启线程的能力,在当前线程完成任务
-(void)createSyncSerial
{
//创建串行队列
dispatch_queue_t queue = dispatch_queue_create("aaa.com", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
NSLog(@"1........%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"2........%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"3........%@",[NSThread currentThread]);
});
}
#pragma --------- 异步串行队列 ------------
//具备开启线程的能力,但是任务是串行的
-(void)createAsyncSerial
{
dispatch_queue_t queue = dispatch_queue_create("aaa.com", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"1........%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"2.......%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"3........%@",[NSThread currentThread]);
});
}
#pragma --------- 同步并行队列 ------------
//不具备开启线程的能力,其实同步的都在主线程,主线程没有串行队列 ,所以并行的功能就没有用了
-(void)createSyncConcurrent
{
//创建一个并发队列
//第一个参数 队列的名字
//第二个参数 类型
//我们自己创建的并发队列
// dispatch_queue_t queue = dispatch_queue_create("sb.com", DISPATCH_QUEUE_CONCURRENT);
//获得全局的并发队列
//第一个参数是优先级,默认的就行了
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_sync(queue, ^{
NSLog(@"1.........%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"2.........%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"3.........%@",[NSThread currentThread]);
});
}
#pragma --------- 异步并行队列 ------------
//最经常使用的就是这个
//异步具备开启子线程的能力,并且并行执行任务
-(void)createAsynConcurrent
{
//获得全局的并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSLog(@"1.......%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"2.......%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"3.......%@",[NSThread currentThread]);
});
NSLog(@"大傻逼");
}
4-GCD网络请求的应用
以请求一张图片为例我们在ViewController的viewDidLoad里面要写上如下代码
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//创建全局的并发队列
dispatch_queue_t queue = dispatch_queue_create("aaa", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSURL *url = [NSURL URLWithString: @"https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1464140268&di=6b6b2e3ea5da34b7da1e02fd28c7acd2&src=http://pic36.nipic.com/20131115/12106414_153522431000_2.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^{
//UI层的东西只有回到主线程里才能设置
self.imgView.image = [UIImage imageWithData:data];
});
});
}
5-GCD函数的使用
延时执行
-(void)creatAfter
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"%@",[NSThread currentThread]);
NSLog(@"皮卡皮卡,皮卡丘");
});
}
快速遍历
-(void)rapidTeaverse
{
for (int i = 0; i < 10; i++) {
NSLog(@"%d",i);
}
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(10, queue, ^(size_t index) {
NSLog(@"%zd %@",index,[NSThread currentThread]);
});
}
组队列
-(void)creatGroup
{
//获取并行队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//创建一个组队列
dispatch_group_t group = dispatch_group_create();
//下载图片1
dispatch_group_async(group, queue, ^{
NSURL *url = [NSURL URLWithString:@"https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1464231860&di=33256b2f206f8082ad634b5250a2b39d&src=http://www.benbenla.cn/images/20120330/benbenla-04b.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
self.image1 = [UIImage imageWithData:data];
});
dispatch_group_async(group, queue, ^{
NSURL *url = [NSURL URLWithString:@"http://www.deskcar.com/desktop/fengjing/200895150214/21.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
self.image2 = [UIImage imageWithData:data];
});
//将图片1和2组合在一起
dispatch_group_notify(group, queue, ^{
//开启一个新的图片上下文
UIGraphicsBeginImageContext(CGSizeMake(375, 667));
//绘制图片
[self.image1 drawInRect:CGRectMake(0, 0, 375/2, 667)];
[self.image2 drawInRect:CGRectMake(375/2, 0, 375/2, 667)];
//取得图片上下文中的图片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
//结束图片上下文
UIGraphicsEndImageContext();
dispatch_async(dispatch_get_main_queue(), ^{
self.imgV.image = image;
});
});
}