多线程
1.进程:一个正在执行的程序。
2.线程: 由一堆不分叉的CPU指令组成的集合。
3.多线程:由多条不分叉的CPU指令组成的集合。
CPU 物理CPU 一个物理CUP能够虚拟成多核CPU,一个物理CPU虚拟成4核,就相当于有四个CPUY,一个CPU同一个时刻 只能执行一个CPU命令。
4.上下文切换:假设一个CUP负责两个线程,当线程1时间片结束以后,会将线程1的相关信系保持倒寄存器中,接下来将时间片分配给线程2,线程2时间片到了以后,又将线程2信息保存起来,接下来唤醒线程1,的寄存器,将其信息取出,接着上一次执行的命令继续执行 来回切换 知道两个线程所有CPU命令执行完成为至。
5.多线程优劣
缺点:
(1)如果大量使用多线程,会占用多内存 影响性能。
(2)资源竞争。解决:上锁。
(3)死锁。
优点:
1.进程:一个正在执行的程序。
2.线程: 由一堆不分叉的CPU指令组成的集合。
3.多线程:由多条不分叉的CPU指令组成的集合。
CPU 物理CPU 一个物理CUP能够虚拟成多核CPU,一个物理CPU虚拟成4核,就相当于有四个CPUY,一个CPU同一个时刻 只能执行一个CPU命令。
4.上下文切换:假设一个CUP负责两个线程,当线程1时间片结束以后,会将线程1的相关信系保持倒寄存器中,接下来将时间片分配给线程2,线程2时间片到了以后,又将线程2信息保存起来,接下来唤醒线程1,的寄存器,将其信息取出,接着上一次执行的命令继续执行 来回切换 知道两个线程所有CPU命令执行完成为至。
5.多线程优劣
缺点:
(1)如果大量使用多线程,会占用多内存 影响性能。
(2)资源竞争。解决:上锁。
(3)死锁。
优点:
提高用户体验。
//==========NSObject==================
// NSObject 开辟一个新线程 简单使用
[self performSelectorInBackground:@selector(getData) withObject:nil];
[self performSelectorInBackground:@selector(getData) withObject:nil];
NSLog(@"===主===%@",[NSThread currentThread]);
-(void)getData
{
NSString *path = @" http://g.hiphotos.baidu.com/zhidao/pic/item/79f0f736afc379313c6f72f8e9c4b74542a911df.jpg";
//将地址转换成URL
NSURL *url = [NSURL URLWithString:path];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
//刷新UI一定时在主线程刷新的。(刷新的时候回到主线程否则会由延迟,只能等待主线程向分线程回收才能刷新中间由时间差);
//显示图片
//回到主线程刷新UI
[self performSelectorOnMainThread:@selector(refreshUI:) withObject:image waitUntilDone:NO];
// self.myImage.image = image;
NSLog(@"======%@",[NSThread currentThread]);
{
NSString *path = @" http://g.hiphotos.baidu.com/zhidao/pic/item/79f0f736afc379313c6f72f8e9c4b74542a911df.jpg";
//将地址转换成URL
NSURL *url = [NSURL URLWithString:path];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
//刷新UI一定时在主线程刷新的。(刷新的时候回到主线程否则会由延迟,只能等待主线程向分线程回收才能刷新中间由时间差);
//显示图片
//回到主线程刷新UI
[self performSelectorOnMainThread:@selector(refreshUI:) withObject:image waitUntilDone:NO];
// self.myImage.image = image;
NSLog(@"======%@",[NSThread currentThread]);
}
-(void)refreshUI:(id)objct
{
self.myImage.image = objct;
NSLog(@"======%@",[NSThread currentThread]);
}
self.myImage.image = objct;
NSLog(@"======%@",[NSThread currentThread]);
}
//========== NSThread==================
// 开辟一个分线程并且立即启动
// [NSThread detachNewThreadSelector:@selector(getData) toTarget:self withObject:nil];
// 需要手动启动
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(getData) object:nil];
//手动启动
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(getData) object:nil];
//手动启动
[thread start];
//分线程
-(void)getData
{
NSString *path = @" http://g.hiphotos.baidu.com/zhidao/pic/item/79f0f736afc379313c6f72f8e9c4b74542a911df.jpg";
//将地址转换成URL
NSURL *url = [NSURL URLWithString:path];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
//刷新UI一定时在主线程刷新的。(刷新的时候回到主线程否则会由延迟,只能等待主线程向分线程回收才能刷新中间由时间差);
//显示图片
//回到主线程刷新UI
[self performSelectorOnMainThread:@selector(refreshUI:) withObject:image waitUntilDone:NO];
// self.myImage.image = image;
NSLog(@"======%@",[NSThread currentThread]);
}
-(void)refreshUI:(id)objct
{
self.myImage.image = objct;
NSLog(@"======%@",[NSThread currentThread]);
-(void)getData
{
NSString *path = @" http://g.hiphotos.baidu.com/zhidao/pic/item/79f0f736afc379313c6f72f8e9c4b74542a911df.jpg";
//将地址转换成URL
NSURL *url = [NSURL URLWithString:path];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
//刷新UI一定时在主线程刷新的。(刷新的时候回到主线程否则会由延迟,只能等待主线程向分线程回收才能刷新中间由时间差);
//显示图片
//回到主线程刷新UI
[self performSelectorOnMainThread:@selector(refreshUI:) withObject:image waitUntilDone:NO];
// self.myImage.image = image;
NSLog(@"======%@",[NSThread currentThread]);
}
-(void)refreshUI:(id)objct
{
self.myImage.image = objct;
NSLog(@"======%@",[NSThread currentThread]);
}
//========== GCD==================
// 1.对于一个串行对列而言 往队列种添加再多的任务也只会产生一个分线程,添加倒队列的执行顺序按添加的顺序执行。
// 2.创建队列时 如果第二个队列为NULL 或者为DISPATCH_QUEUE_SERIAL 创建的是串行对列 如果为DISPATCH_QUEUE_CONCURRENT 时并行对列 并行队列只要添加任务就会产生新线程。
// 串行队列中只有一个线程
// 并行对列由多个线程
// 2.创建队列时 如果第二个队列为NULL 或者为DISPATCH_QUEUE_SERIAL 创建的是串行对列 如果为DISPATCH_QUEUE_CONCURRENT 时并行对列 并行队列只要添加任务就会产生新线程。
// 串行队列中只有一个线程
// 并行对列由多个线程
// 刷新UI一定要回到主线程
dispatch_queue_t queue = dispatch_queue_create("com", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
// 耗时3秒
sleep(3);//耗时操作 如:下载数据 数据存库 涂鸦 等
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"任务1完成");
});
NSLog(@"任务1完成");
});
});
// 任务2
dispatch_async(queue, ^{
// 耗时1秒
sleep(1);
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"任务2完成");
});
});
sleep(1);
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"任务2完成");
});
});
// 任务3
dispatch_async(queue, ^{
// 耗时4秒
sleep(4);
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"任3完成");
});
});
sleep(4);
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"任3完成");
});
});
==========GCD监听并行========
// 1.创建并行对列
dispatch_queue_t queue = dispatch_queue_create("com", DISPATCH_QUEUE_CONCURRENT);
// 2.创建Group
dispatch_group_t group = dispatch_group_create();
// 3.将任务添加倒对列种
// (任务1)
dispatch_group_async(group, queue, ^{
sleep(3);
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"任务一完成");
});
});
// (任务2)
dispatch_group_async(group, queue, ^{
sleep(1);
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"任务二完成");
});
});
// (任务3)
dispatch_group_async(group, queue, ^{
sleep(4);
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"任务三完成");
});
dispatch_group_async(group, queue, ^{
sleep(3);
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"任务一完成");
});
});
// (任务2)
dispatch_group_async(group, queue, ^{
sleep(1);
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"任务二完成");
});
});
// (任务3)
dispatch_group_async(group, queue, ^{
sleep(4);
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"任务三完成");
});
});
// 4.通过Group 监听并行队列完成任务
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"任务完成");
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"任务完成");
});