// NSObject
// 在子线程中执行代码
// 参数1: 执行的方法 (最多有一个参数,没有返回值)
// 参数2: 传递给方法的参数
// [self performSelectorInBackground:@selector(cycling:) withObject:@"obj1"];
// 回到主线程更新页面
// [self performSelectorOnMainThread:@selector(updateUI:) withObject:nil waitUntilDone:YES];
// NSThread
// 进入子线程
// NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(cycling:) object:@"thread"];
// [thread start]; // 启动线程执行
// [thread release];
//
// // 直接启动
// [NSThread detachNewThreadSelector:@selector(cycling:) toTarget:self withObject:@"thread2"];
// NSOperation
/*
// 通常使用NSOperation下的两个子类:NSInvocationOperation、NSBlockOperation
// NSInvocationOperation
NSInvocationOperation *invocationOperation = [[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(cycling:) object:@"invocationOperation"] autorelease];
// [invocationOperation start]; // 启动任务
// NSBlockOperation
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 10000; i++) {
NSLog(@"blockOperation: %i", i);
}
}];
// [blockOperation start]; // 启动任务
// 创建一个任务队列,NSOperationQueue
NSOperationQueue *operationQueue = [[NSOperationQueue new] autorelease];
// 当blockOperation中的任务执行完毕后,invocationOperation才开始执行
// [invocationOperation addDependency:blockOperation];
// 设置同时执行任务最大数
operationQueue.maxConcurrentOperationCount = 1;
// 添加任务到队列中
[operationQueue addOperation:blockOperation];
[operationQueue addOperation:invocationOperation];
*/
/**
* GCD 分发队列 遵守FIFO原则
* 串行队列:当一个任务执行完之后,才可以进行下一个任务的执行
* 并行队列:任务在派发的时候是有顺序的,不用等到上一个任务执行完成之后再执行,同时执行
*/
/**
* 脱离线程:当线程内部的代码执行完毕之后,线程自动关闭。例如:NSThread / NSObject
* 非脱离线程:当线程内部的代码执行完毕之后,线程不关闭,等待着下一次的使用。例如:NSOperationQueue
*/
// 1. GCD 使用主队列实现任务的串行,主队列分派的任务,永远在主线程中
dispatch_queue_t mainQueue = dispatch_get_main_queue();
// dispatch_async(mainQueue, ^{
// for (int i = 0; i < 1000; i++) {
// NSLog(@"第一个任务:%d %@", i, [NSThread currentThread]);
// }
// });
// dispatch_async(mainQueue, ^{
// for (int i = 0; i < 1000; i++) {
// NSLog(@"第二个任务:%d %@", i, [NSThread currentThread]);
// }
// });
// dispatch_async(mainQueue, ^{
// for (int i = 0; i < 1000; i++) {
// NSLog(@"第三个任务:%d %@", i, [NSThread currentThread]);
// }
// });
// 2. 使用自己创建出来的队列,实现任务的串行,新队列执行的任务,在子线程中执行
// 参数1: 队列的标示
// 参数2: 类型
dispatch_queue_t myQueue = dispatch_queue_create("com.lanou3g.lesson_22.myQueue", DISPATCH_QUEUE_SERIAL);
// dispatch_async(myQueue, ^{
// for (int i = 0; i < 1000; i++) {
// NSLog(@"第一个任务:%d %@", i, [NSThread currentThread]);
// }
// });
// dispatch_async(myQueue, ^{
// for (int i = 0; i < 1000; i++) {
// NSLog(@"第二个任务:%d %@", i, [NSThread currentThread]);
// }
// });
// dispatch_async(myQueue, ^{
// for (int i = 0; i < 1000; i++) {
// NSLog(@"第三个任务:%d %@", i, [NSThread currentThread]);
// }
// });
// 3. 使用自己创建的队列,实现任务的并行,执行的任务在不同的子线程中执行
dispatch_queue_t myQueue2 = dispatch_queue_create("com.lanou3g.lesson_22.myQueue2", DISPATCH_QUEUE_CONCURRENT);
// dispatch_async(myQueue2, ^{
// for (int i = 0; i < 1000; i++) {
// NSLog(@"第一个任务:%d %@", i, [NSThread currentThread]);
// }
// });
// dispatch_async(myQueue2, ^{
// for (int i = 0; i < 1000; i++) {
// NSLog(@"第二个任务:%d %@", i, [NSThread currentThread]);
// }
// });
// dispatch_async(myQueue2, ^{
// for (int i = 0; i < 1000; i++) {
// NSLog(@"第三个任务:%d %@", i, [NSThread currentThread]);
// }
// });
// 4. 使用系统的globle队列,实现任务的并行,在子线程中
dispatch_queue_t globleQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// dispatch_async(globleQueue, ^{
// for (int i = 0; i < 1000; i++) {
// NSLog(@"第一个任务:%d %@", i, [NSThread currentThread]);
// }
// });
// dispatch_async(globleQueue, ^{
// for (int i = 0; i < 1000; i++) {
// NSLog(@"第二个任务:%d %@", i, [NSThread currentThread]);
// }
// });
// dispatch_async(globleQueue, ^{
// for (int i = 0; i < 1000; i++) {
// NSLog(@"第三个任务:%d %@", i, [NSThread currentThread]);
// }
// });
// 让代码只执行一次
for (int i = 0; i < 1000000; i++) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"只执行一次");
});
}
// 让一段代码执行多次
dispatch_apply(10, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t t) {
NSLog(@"多次执行");
});
// 让代码延迟几秒执行
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"延迟5秒执行");
});
/**
* 1. 发送网络请求,获取网络数据的时候需要使用多线程(但是:我们创建网络请求的时候并不需要单独去开启子线程,系统会在方法内部帮我们做这件事)
* 2. 当有耗时很长的计算的时候,建议使用多线程
* 3. 当处理数据库中,或者其它位置大量数据的时候使用多线程
* 4. 总结:将耗时比较长的代码,都放到子线程中运行
* 5. 重点:页面的刷新必须回到主线程中
*/
}
#pragma mark 循环
- (void)cycling:(id)obj
{
for (int i = 0; i < 10000; i++) {
NSLog(@"%@: %d", obj, i);
}
}
#pragma mark 发送网络图片请求
- (void)sendRequestForImageWithUrlStr:(NSString *)urlStr
{
// http://pic.sucaiw.com/up_files/bizhi/a09ba7547e/sucaiw-cdscbj4023.jpg
// 1. 直接通过NSData获取网络资源数据
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://pic.sucaiw.com/up_files/bizhi/a09ba7547e/sucaiw-cdscbj4023.jpg"]];
// 2. 更新图片
// 参数1: 主线程执行的方法
// 参数2: 传递给方法的参数
// 参数3: 是否等待子线程内执行完毕
[self performSelectorOnMainThread:@selector(updateUI:)
withObject:[UIImage imageWithData:data]
waitUntilDone:YES];
}
#pragma mark - 更新页面
- (void)updateUI:(UIImage *)image
{
_imageView.image = image;
}
- (IBAction)buttonAction:(UIButton *)sender
{
// [self sendRequestForImageWithUrlStr:nil];
// 子线程中请求图片
// [self performSelectorInBackground:@selector(sendRequestForImageWithUrlStr:) withObject:nil];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
for (int i = 0; i < 10; i++) {
NSLog(@"%d", i);
}
});