/*
进程 : 正在活动 ( 运行的 ) 一个运用程序 就是一个进程
每一个进程至少有一条线程 叫主线程
线程 : 每一个线程都是独立的可以执行任务
除了主线程以为的都叫子线程
子线程可以有很多个但是线程是耗费资源的
( 一般最多不超过 5 条 注 :3 条最佳 )
程序退出后会清空线程的任务
主线程操作什么样的任务 ?
UI 界面 按钮点击 屏幕的滚动 ( 一切用户看到见的 都要在主线程当中去操作 )
比较大的耗时操作 又或者用户看不见的操作可以放到子线程当中去做比如下载解压缩读取大型数据等可以在子线程中操作
多线程原理 :
cpu 工作时 同一时间只能执行一个任务之所有可以造成多条线程一起执行任务的假象是 cpu 在进行高速的切换 ( 调度 ) 在线程之间切换来达到多个任务一起执行的效果
说说多线程优点 :
1. 可以大大提高执行任务的效率
2. 可以让用户有更好的用户体验
缺点 :
如果大量的开辟线程会造成程序的卡顿 ( 耗费过量的资源 )
如果理想化
缺点 :
进程 : 正在活动 ( 运行的 ) 一个运用程序 就是一个进程
每一个进程至少有一条线程 叫主线程
线程 : 每一个线程都是独立的可以执行任务
除了主线程以为的都叫子线程
子线程可以有很多个但是线程是耗费资源的
( 一般最多不超过 5 条 注 :3 条最佳 )
程序退出后会清空线程的任务
主线程操作什么样的任务 ?
UI 界面 按钮点击 屏幕的滚动 ( 一切用户看到见的 都要在主线程当中去操作 )
比较大的耗时操作 又或者用户看不见的操作可以放到子线程当中去做比如下载解压缩读取大型数据等可以在子线程中操作
多线程原理 :
cpu 工作时 同一时间只能执行一个任务之所有可以造成多条线程一起执行任务的假象是 cpu 在进行高速的切换 ( 调度 ) 在线程之间切换来达到多个任务一起执行的效果
说说多线程优点 :
1. 可以大大提高执行任务的效率
2. 可以让用户有更好的用户体验
缺点 :
如果大量的开辟线程会造成程序的卡顿 ( 耗费过量的资源 )
如果理想化
缺点 :
*/
//查看当前线程的方法
NSLog(@"--%@",[NSThread currentThread]);
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//该方法在哪个线程调用 该方法的线程就是那个线程
[self performSelector:@selector(download:) withObject:@"123" ];
//开辟了一个子线程
//方法是基类提供的只要是对象都能调用
[self performSelectorInBackground:@selector(test:) withObject:@"1"];
#pragma mark -- NSThread
// 初始化 开辟一个子线程
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(thread) object:nil];
[thread start];
[NSThread exit];
[NSThread detachNewThreadSelector:@selector(thread:) toTarget:self withObject:@"1"];
}
- (void)thread:(NSString *)str
{
// 线程 休眠 (延迟执行效果)
[NSThread sleepForTimeInterval:3];
NSLog(@"--%@",[NSThread currentThread]);
NSLog(@"%d",[NSThread isMainThread]);
}
{
//该方法在哪个线程调用 该方法的线程就是那个线程
[self performSelector:@selector(download:) withObject:@"123" ];
//开辟了一个子线程
//方法是基类提供的只要是对象都能调用
[self performSelectorInBackground:@selector(test:) withObject:@"1"];
#pragma mark -- NSThread
// 初始化 开辟一个子线程
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(thread) object:nil];
[thread start];
[NSThread exit];
[NSThread detachNewThreadSelector:@selector(thread:) toTarget:self withObject:@"1"];
}
- (void)thread:(NSString *)str
{
// 线程 休眠 (延迟执行效果)
[NSThread sleepForTimeInterval:3];
NSLog(@"--%@",[NSThread currentThread]);
NSLog(@"%d",[NSThread isMainThread]);
}
/*
常用的开启多线程的方法
优势:不用程序员 管理 线程的生命周期
1.NSOperation 封装一下gcd的方法提高OC的语法来使用GCD
2.GCD 是苹果推荐的 可以最大化的发挥多核cpu 是C语言函数
NSOperation 是一个抽象类
NSBlockOperation
NSInvocationOperation
线程队列(任务中心 指定很多任务)
1.串行队列 主线程相当于一个串行队列 队列中的任务 需要一个执行完毕后在执行下一个
2.并行队列 队列中的任务 进行并发执行 同时开始未必同时结束
同步:没有开启子线程的能力
异步:拥有开启子线程的能力
任务是什么?
比如 下载 打印 都是个任务
使用GCD 或者 NSOperation 我们只需往合适的队列中添加任务 其他的让系统根据队列类型去完成任务
线程之间的通信
在子线程中完成耗时的操作完成后需要回到主线程进行UI刷新
主线程 与 子线程 是独立的
//开启子线程 请求一张图片 请求完成后 回到主线程
//刷新UI
*/
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//需要把NSInvocationOperation 对象 放进一个队列里 才能开启子线程
//创建一个队列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//给队列提供一个 可以设置 最大并发数
queue.maxConcurrentOperationCount = 2;
//一次最多并发执行2个任务
//开启一个线程
NSInvocationOperation *operaion = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download:) object:@"11"];
// 把任务添加到队列里
// 只需要把任务添加进队列中 不需要我们来操作会自动执行
// 不是添加一个任务就开启一个线程
// 这个操作是系统给我们做的 有的线程会被系统重复利用
[queue addOperation:operaion];
// 往队列中添加任务
[queue addOperationWithBlock:^{
//block中就是你要添加的任务
NSLog(@"%@",[NSThread currentThread]);
}];
// 初始化一个任务
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@",[NSThread currentThread]);
}];
[queue addOperation:blockOperation];
常用的开启多线程的方法
优势:不用程序员 管理 线程的生命周期
1.NSOperation 封装一下gcd的方法提高OC的语法来使用GCD
2.GCD 是苹果推荐的 可以最大化的发挥多核cpu 是C语言函数
NSOperation 是一个抽象类
NSBlockOperation
NSInvocationOperation
线程队列(任务中心 指定很多任务)
1.串行队列 主线程相当于一个串行队列 队列中的任务 需要一个执行完毕后在执行下一个
2.并行队列 队列中的任务 进行并发执行 同时开始未必同时结束
同步:没有开启子线程的能力
异步:拥有开启子线程的能力
任务是什么?
比如 下载 打印 都是个任务
使用GCD 或者 NSOperation 我们只需往合适的队列中添加任务 其他的让系统根据队列类型去完成任务
线程之间的通信
在子线程中完成耗时的操作完成后需要回到主线程进行UI刷新
主线程 与 子线程 是独立的
//开启子线程 请求一张图片 请求完成后 回到主线程
//刷新UI
*/
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//需要把NSInvocationOperation 对象 放进一个队列里 才能开启子线程
//创建一个队列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//给队列提供一个 可以设置 最大并发数
queue.maxConcurrentOperationCount = 2;
//一次最多并发执行2个任务
//开启一个线程
NSInvocationOperation *operaion = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download:) object:@"11"];
// 把任务添加到队列里
// 只需要把任务添加进队列中 不需要我们来操作会自动执行
// 不是添加一个任务就开启一个线程
// 这个操作是系统给我们做的 有的线程会被系统重复利用
[queue addOperation:operaion];
// 往队列中添加任务
[queue addOperationWithBlock:^{
//block中就是你要添加的任务
NSLog(@"%@",[NSThread currentThread]);
}];
// 初始化一个任务
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@",[NSThread currentThread]);
}];
[queue addOperation:blockOperation];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//开启一个子线程
[self performSelectorInBackground:@selector(downLoad:) withObject:@"http://pic2.ooopic.com/01/03/51/25b1OOOPIC19.jpg"];
}
// 实现请求图片
- (void)downLoad:(NSString *)str
{
NSLog(@"--%@",[NSThread currentThread]);
//图片请求(请求data 就是耗时操作)
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:str]];
//回到主线程 显示图片
//waitUntilDone 是否等待回答主线程的方法执行完毕后在向下执行
// [self performSelectorOnMainThread:@selector(imageView:) withObject:data waitUntilDone:YES];
// NSLog(@"123123");
// 回到主线程方法2
// NSThread mainThread 获取主线程
[self performSelector:@selector(imageView:) onThread:[NSThread mainThread] withObject:data waitUntilDone:YES];
}
- (void)imageView:(NSData *)data
{
//显示图片
self.imagev.image = [UIImage imageWithData:data];
NSLog(@"--%@",[NSThread currentThread]);
}
{
//开启一个子线程
[self performSelectorInBackground:@selector(downLoad:) withObject:@"http://pic2.ooopic.com/01/03/51/25b1OOOPIC19.jpg"];
}
// 实现请求图片
- (void)downLoad:(NSString *)str
{
NSLog(@"--%@",[NSThread currentThread]);
//图片请求(请求data 就是耗时操作)
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:str]];
//回到主线程 显示图片
//waitUntilDone 是否等待回答主线程的方法执行完毕后在向下执行
// [self performSelectorOnMainThread:@selector(imageView:) withObject:data waitUntilDone:YES];
// NSLog(@"123123");
// 回到主线程方法2
// NSThread mainThread 获取主线程
[self performSelector:@selector(imageView:) onThread:[NSThread mainThread] withObject:data waitUntilDone:YES];
}
- (void)imageView:(NSData *)data
{
//显示图片
self.imagev.image = [UIImage imageWithData:data];
NSLog(@"--%@",[NSThread currentThread]);
}
/*
1.并行队列 系统提供了一个 全局并行队列(整个应用都可以使用)如果不想用也可以创建一个
2.串行队列 需要创建一个出来
任务:
1.同步 不具备开启线程的能力
2.异步 具有开启线程的能力
分四种情况
1.并行 --- 异步任务
2.并行 --- 同步任务
3.串行 --- 异步任务
4.串行 --- 同步任务
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//执行的任务 在整个程序运行期间只执行一次
//并且只允许 一个线程访问(自带 线程保护)
});
*/
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// [self asyncGlobalQueue];
// [self syncGlobalQueue];
// [self asyncSerialQueue];
// [self syncSerialqueue];
self.ticketsCount = 100;
[self tickets];
}
// 模拟卖票 需要添加同步锁(互斥锁)
- (void)tickets
{
// 创建并行队列 添加异步任务
dispatch_queue_t queue = dispatch_queue_create("213", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[self setTikets];
});
dispatch_async(queue, ^{
[self setTikets];
});
dispatch_release(queue);
#pragma mark -- GCD开启子线程加载图片 回到主线程刷新UI
dispatch_queue_t queue12 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
//请求的超时操作(同步请求)
//在子线程中同步请求就相当于异步请求
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://pic2.ooopic.com/01/03/51/25b1OOOPIC19.jpg"]];
UIImage *image = [UIImage imageWithData:data];
//回到主线程刷新
//dispatch_get_main_queue() 活到主线程
dispatch_async(dispatch_get_main_queue(), ^{
//回到主线程执行的任务
//刷新UI
});
});
}
// 卖票
- (void)setTikets
{
while (1) {
@synchronized(self)
{
if (self.ticketsCount > 0 ) {
self.ticketsCount--;
NSLog(@"%ld---%@",self.ticketsCount,[NSThread currentThread]);
}else
{
return;
}
}
}
}
// 1.并行 --- 异步任务
// 开启子线程 并且 任务并发
-(void)asyncGlobalQueue
{
// 获取全局的并发队列
// dispatch_queue_t队列的类型
// 参数1 是cpu切换的频率高度(切换的优先级)
// 参数2 是个预留参数可以添0
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//添加异步任务
// 参数1 给那个队列添加任务
// 参数2 任务
dispatch_async(queue, ^{
NSLog(@"---任务1--%@",[NSThread currentThread]);
// NSLog(@"---任务2--%@",[NSThread currentThread]);
// NSLog(@"---任务3--%@",[NSThread currentThread]);
// NSLog(@"---任务4--%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
// NSLog(@"---任务1--%@",[NSThread currentThread]);
NSLog(@"---任务2--%@",[NSThread currentThread]);
// NSLog(@"---任务3--%@",[NSThread currentThread]);
// NSLog(@"---任务4--%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
// NSLog(@"---任务1--%@",[NSThread currentThread]);
// NSLog(@"---任务2--%@",[NSThread currentThread]);
NSLog(@"---任务3--%@",[NSThread currentThread]);
// NSLog(@"---任务4--%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
// NSLog(@"---任务1--%@",[NSThread currentThread]);
// NSLog(@"---任务2--%@",[NSThread currentThread]);
// NSLog(@"---任务3--%@",[NSThread currentThread]);
NSLog(@"---任务4--%@",[NSThread currentThread]);
});
}
// 2.并行 --- 同步任务
// 没有开启子线程 相当于变成了一个串行队列
-(void)syncGlobalQueue
{
// 创建一个并行队列
// 参数1 队列标识符 反向域名 com.lanou3g.www
// 参数2 填你要创建的队列 的类型(串SERIAL/并CONCURRENT)
dispatch_queue_t queue = dispatch_queue_create("com.lanou3g.www", DISPATCH_QUEUE_CONCURRENT);
//添加同步任务
dispatch_sync(queue, ^{
NSLog(@"---任务1--%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"---任务2--%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"---任务3--%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"---任务4--%@",[NSThread currentThread]);
});
// 创建的队列 是需要释放的(ARC 不用释放的)
dispatch_release(queue);
}
//3.串行 --- 异步任务
// 开启了子线程 串行
- (void)asyncSerialQueue
{
//创建串行队列
dispatch_queue_t queue = dispatch_queue_create("www", DISPATCH_QUEUE_SERIAL);
//添加异步任务
dispatch_async(queue, ^{
NSLog(@"---任务1--%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"---任务2--%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"---任务3--%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"---任务4--%@",[NSThread currentThread]);
});
dispatch_release(queue);
}
//4.串行 --- 同步任务
// 不开子线程 串行
- (void)syncSerialqueue
{
dispatch_queue_t queue = dispatch_queue_create("we", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
NSLog(@"---任务1--%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"---任务2--%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"---任务3--%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"---任务4--%@",[NSThread currentThread]);
});
// 创建的队列 是需要释放的(ARC 不用释放的)
dispatch_release(queue);
}
1.并行队列 系统提供了一个 全局并行队列(整个应用都可以使用)如果不想用也可以创建一个
2.串行队列 需要创建一个出来
任务:
1.同步 不具备开启线程的能力
2.异步 具有开启线程的能力
分四种情况
1.并行 --- 异步任务
2.并行 --- 同步任务
3.串行 --- 异步任务
4.串行 --- 同步任务
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//执行的任务 在整个程序运行期间只执行一次
//并且只允许 一个线程访问(自带 线程保护)
});
*/
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// [self asyncGlobalQueue];
// [self syncGlobalQueue];
// [self asyncSerialQueue];
// [self syncSerialqueue];
self.ticketsCount = 100;
[self tickets];
}
// 模拟卖票 需要添加同步锁(互斥锁)
- (void)tickets
{
// 创建并行队列 添加异步任务
dispatch_queue_t queue = dispatch_queue_create("213", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[self setTikets];
});
dispatch_async(queue, ^{
[self setTikets];
});
dispatch_release(queue);
#pragma mark -- GCD开启子线程加载图片 回到主线程刷新UI
dispatch_queue_t queue12 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
//请求的超时操作(同步请求)
//在子线程中同步请求就相当于异步请求
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://pic2.ooopic.com/01/03/51/25b1OOOPIC19.jpg"]];
UIImage *image = [UIImage imageWithData:data];
//回到主线程刷新
//dispatch_get_main_queue() 活到主线程
dispatch_async(dispatch_get_main_queue(), ^{
//回到主线程执行的任务
//刷新UI
});
});
}
// 卖票
- (void)setTikets
{
while (1) {
@synchronized(self)
{
if (self.ticketsCount > 0 ) {
self.ticketsCount--;
NSLog(@"%ld---%@",self.ticketsCount,[NSThread currentThread]);
}else
{
return;
}
}
}
}
// 1.并行 --- 异步任务
// 开启子线程 并且 任务并发
-(void)asyncGlobalQueue
{
// 获取全局的并发队列
// dispatch_queue_t队列的类型
// 参数1 是cpu切换的频率高度(切换的优先级)
// 参数2 是个预留参数可以添0
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//添加异步任务
// 参数1 给那个队列添加任务
// 参数2 任务
dispatch_async(queue, ^{
NSLog(@"---任务1--%@",[NSThread currentThread]);
// NSLog(@"---任务2--%@",[NSThread currentThread]);
// NSLog(@"---任务3--%@",[NSThread currentThread]);
// NSLog(@"---任务4--%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
// NSLog(@"---任务1--%@",[NSThread currentThread]);
NSLog(@"---任务2--%@",[NSThread currentThread]);
// NSLog(@"---任务3--%@",[NSThread currentThread]);
// NSLog(@"---任务4--%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
// NSLog(@"---任务1--%@",[NSThread currentThread]);
// NSLog(@"---任务2--%@",[NSThread currentThread]);
NSLog(@"---任务3--%@",[NSThread currentThread]);
// NSLog(@"---任务4--%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
// NSLog(@"---任务1--%@",[NSThread currentThread]);
// NSLog(@"---任务2--%@",[NSThread currentThread]);
// NSLog(@"---任务3--%@",[NSThread currentThread]);
NSLog(@"---任务4--%@",[NSThread currentThread]);
});
}
// 2.并行 --- 同步任务
// 没有开启子线程 相当于变成了一个串行队列
-(void)syncGlobalQueue
{
// 创建一个并行队列
// 参数1 队列标识符 反向域名 com.lanou3g.www
// 参数2 填你要创建的队列 的类型(串SERIAL/并CONCURRENT)
dispatch_queue_t queue = dispatch_queue_create("com.lanou3g.www", DISPATCH_QUEUE_CONCURRENT);
//添加同步任务
dispatch_sync(queue, ^{
NSLog(@"---任务1--%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"---任务2--%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"---任务3--%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"---任务4--%@",[NSThread currentThread]);
});
// 创建的队列 是需要释放的(ARC 不用释放的)
dispatch_release(queue);
}
//3.串行 --- 异步任务
// 开启了子线程 串行
- (void)asyncSerialQueue
{
//创建串行队列
dispatch_queue_t queue = dispatch_queue_create("www", DISPATCH_QUEUE_SERIAL);
//添加异步任务
dispatch_async(queue, ^{
NSLog(@"---任务1--%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"---任务2--%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"---任务3--%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"---任务4--%@",[NSThread currentThread]);
});
dispatch_release(queue);
}
//4.串行 --- 同步任务
// 不开子线程 串行
- (void)syncSerialqueue
{
dispatch_queue_t queue = dispatch_queue_create("we", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
NSLog(@"---任务1--%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"---任务2--%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"---任务3--%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"---任务4--%@",[NSThread currentThread]);
});
// 创建的队列 是需要释放的(ARC 不用释放的)
dispatch_release(queue);
}