//
// ViewController.m
// UI_Lesson_21
//
// Created by xalo on 15/10/7.
// Copyright © 2015年 . All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@property (retain, nonatomic) IBOutlet UIImageView *iamgeView;
@property (retain, nonatomic) IBOutlet UIActivityIndicatorView *activitayIndicator;
@implementation ViewController
- (IBAction)HhandleButtonAction:(id)sender {
// 应用程序进程会默认开辟一个线程 -- 主线程 主线程的作用是更新UI姐买呢 如果应用程序在允许过程中不开辟其他线程 只有主线程可以完成任务炒作 这种情形称为单线程应用 单线程会出现一定程度的代码阻塞 导致界面假死
//开辟子线程方法一:
//开辟新的子线程并附加对应的方法 等待被执行
// NSThread *aTharead = [[[NSThread alloc]initWithTarget:self selector:@selector(calculate) object:nil] autorelease];
// //为子线程对象发送start消息 开启线程 执行相关方法
// //添加线程对象名
// aTharead.name = @"我是NO.1";
// //开启线程
// [aTharead start];
//
// //开辟子线程方法二:
// [NSThread detachNewThreadSelector:@selector(calculate) toTarget:self withObject:nil];
//如果子线程的对应方法 内部 在双创建带有autorelease的对象 必须要添加创建一个自动释放池 否则对象无法释放
// [NSThread detachNewThreadSelector:@selector(downloadImage) toTarget:self withObject:nil];
/*
[self.activitayIndicator startAnimating];
//创建NSInvocationOperation
NSInvocationOperation *invoOperation = [[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(calculate) object:nil] autorelease];
// [invoOperation start];
//创建NSBlockOperation
NSBlockOperation *blockOperation =[NSBlockOperation blockOperationWithBlock:^{
[self downloadImage];
}];
// [blockOperation start];
//创建操作队列 通过操作队列 完成操作对象的执行
//创建主线程队列(任务主线程执行)
// NSOperationQueue *queue = [NSOperationQueue mainQueue];
//自己创建队列 (任务会提交子线程执行)
NSOperationQueue *queue = [[[NSOperationQueue alloc]init] autorelease];//自己创建的操作队列在执行相关的操作对象是 会根据需求开辟子线程去执行
//设置最大并发数
//最大并发数为1时 表示队列被顺序执行 只有前一个操作完成后才继续执行下一个操作
[queue setMaxConcurrentOperationCount:2];
//设置操作队列优先级
[blockOperation setQueuePriority:NSOperationQueuePriorityVeryHigh];
[invoOperation setQueuePriority:NSOperationQueuePriorityVeryLow];
[queue addOperation:blockOperation];
[queue addOperation: invoOperation];
*/
[self grandCentralDispatchMethod];
}
//GCD的核心是使用分发队列来管理任务的执行 分发队列分为两种 : 一种是serial(串行) 一种是concurrent(并发) 两种都严格遵守FIFO(先进先出)
- (void)grandCentralDispatchMethod{
/*
//1获取serial queue的两种方式
//获取主线程队列 mainQueue 会在主线程中执行 即:主线程会执行mainQueue中的各个任务
dispatch_queue_t mainQueue = dispatch_get_main_queue();//dispatch_get_main_queue获取主线程队列 串行队列
//为主线程提交任务 任务以block 形式提交
//dispatch_async异步执行 主线程交替执行函数 (不会卡顿)(_async并发执行)
dispatch_async(mainQueue, ^{
NSLog( @"第二个任务");
[self calculate];
});//在block中写要被执行的代码片段 也可以是方法的调用
//dispatch_sync同步提交任务函数(_sync串行执行)
dispatch_sync(mainQueue, ^{
NSLog( @"第三个任务");
[self downloadImage];
});
*/
/*
//除了可以获取 主队列的这种串行队列 还可以自己根据需求创建串行队列
//自定义的串行队列在分发执行任务是通过开辟子线程执行的
//GCD队列(dispatch queue) dispatch_queue_t
dispatch_queue_t mySerialQueue = dispatch_queue_create("cGCD.mySerialQueue", DISPATCH_QUEUE_SERIAL);//dispatch_queue_create 创建队列方法 //参数一 给当前创建的队列起名字 苹果推荐使用反向的域名形式 //参数二 DISPATCH_QUEUE_SERIAL 创建的队列类型private dispatch queues串行队列 指定当前创建队列的类型 分为Srial 和concurrent 两种(即:串行和并发 )
dispatch_async(mySerialQueue, ^{
NSLog( @"first mission :%@", [NSThread isMainThread] ? @"main thread":@"isn't main tread");
});
dispatch_async(mySerialQueue, ^{
NSLog( @"second mission :%@", [NSThread isMainThread] ? @"main thread":@"isn't main tread");
});
dispatch_async(mySerialQueue, ^{
NSLog( @"thread mission :%@", [NSThread isMainThread] ? @"main thread":@"isn't main tread");
});
*/
//获取并发队列的两种方法
/*
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);//dispatch_get_global_queue 获取global dispatch queue 并发队列//第一个参数是用来控制队列的优先级 //参数二是苹果的预留参数 未来才会使用 现在设置为0(必须)
//globalQueue作为并发队列 会开辟是若干/个子线程并发执行 多个提交的任务(开始较晚的不一定晚结束 开始早的不一定会最先结束 )
dispatch_async(globalQueue, ^{
NSLog( @"first mission :%@", [NSThread isMainThread] ? @"main thread":@"isn't main tread");
[self downloadImage];
});
dispatch_async(globalQueue, ^{
NSLog( @"second mission :%@", [NSThread isMainThread] ? @"main thread":@"isn't main tread");
[self calculate];
});
*/
//自己创建并发队列
dispatch_queue_t myConcurrentQueue = dispatch_queue_create("com..GCD.myconcurrentQueue", DISPATCH_QUEUE_CONCURRENT);//dispatch_queue_create 创建队列 "com..GCD.myconcurrentQueue" 给当前创建的队列起名字 苹果推荐使用反
/*
向的域名形式 DISPATCH_QUEUE_CONCURRENT 队列类型 CONCURRENT并发
dispatch_async(myConcurrentQueue, ^{
NSLog( @"first mission :%@", [NSThread isMainThread] ? @"main thread":@"isn't main tread");
[self downloadImage];
});
dispatch_async(myConcurrentQueue, ^{
NSLog( @"second mission :%@", [NSThread isMainThread] ? @"main thread":@"isn't main tread");
[self calculate];
});
//延时提交某个任务到分发队列中(延时执行任务可以在mainQueue中正常执行 在自定义的队列中执行就会出现问题)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog( @"延时3s执行任务");
});
*/
/*
//创建任务组
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, myConcurrentQueue, ^{
NSLog( @"任务一");
});
dispatch_group_async(group, myConcurrentQueue, ^{
NSLog( @"任务二");
[self calculate];
});
//dispatch_group_notify 中的方法会等待group中的成员执行完了之后再执行
dispatch_group_notify(group, myConcurrentQueue, ^{
NSLog( @"任务三");
});
*/
//为了保证数据访问是的安全性 , 可以使用serial queue 来解决访问安全性问题
//serial queue 缺陷:后面的任务必须等待前面的任务结束后才能执行 降低数据读取的效率
//如果只是读取数据 适合使用concurrent queue 来执行
dispatch_async(myConcurrentQueue, ^{
NSLog( @"读取数据任务一");
});
dispatch_async(myConcurrentQueue, ^{
NSLog( @"读取数据任务二");
});
dispatch_async(myConcurrentQueue, ^{
NSLog( @"读取数据任务三");
});
//dispatch_barrier_async (它之前的并发执行完---它执行---它执行完, 它之后的再并发执行) 并发执行中这个方法会执行结束之后之后的方法才能执行 有利于保证数据安全 会等待它之前提交的任务并发执行结束后才开始执行 并且执行完成之后才开始其之后提交的任务 像一道墙 隔开了之前和之后提交的任务 这样的操作可以保证读写安全性 也可以提高读写的效率
dispatch_barrier_async(myConcurrentQueue, ^{
NSLog( @"写入数据任务");
[self calculate];
});
dispatch_async(myConcurrentQueue, ^{
NSLog( @"读取数据任务四");
});
dispatch_async(myConcurrentQueue, ^{
NSLog( @"读取数据任务五");
});
for (int i = 0 ;i < 10; i ++) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"任务被执行%d次", i+ 1);
});
}
/*
//苹果推荐使用dispatch_once来定义单例方法
+(id)shareInstance{
static FooClass *object = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
object = [[FooClass alloc]init];
});
return object;
}
*/
}
- (void)downloadImage{
NSLog( @"下载图片");
//同步
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString: @"http://www.pp3.cn/uploads/allimg/111111/100519C19-1.jpg"]];
//回到主线程 由主线程取更新UI界面
[self performSelectorOnMainThread:@selector(updataUserInterface:) withObject:imageData waitUntilDone:YES];
}
- (void)updataUserInterface:(NSData *)data{
[self.activitayIndicator stopAnimating];;
self.iamgeView.image = [UIImage imageWithData:data];
}
- (void)calculate{
NSLog( @"计算");
// NSLog( @"线程:%@ 是否是主线程:%@", [NSThread currentThread], [NSThread isMainThread]?@"是": @"否");
NSInteger count = 0 ;
for (NSInteger i = 0 ; i < 635500000; i ++) {
count += i ;
// @autoreleasepool {
// NSArray *array = [[[NSArray alloc]init] autorelease];
//
// }
}
NSLog( @"%ld", count);
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc {
[_iamgeView release];
[_activitayIndicator release];
[super dealloc];
}
@end
来源:oschina
链接:https://my.oschina.net/u/2503139/blog/524170