经常使用的GCD
// ViewController.m // 07-GCD的基本使用 #import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self syncConcurrent]; }
这个很重要: 出八阿哥 死循环了?
/** * 同步函数 + 主队列: */ 同步:多个任务一个接着一个的执行,会等待;
异步:多个任务同时都在执行,不会等待; - (void)syncMain { NSLog(@"syncMain ----- begin"); // 1.获得主队列 dispatch_queue_t queue = dispatch_get_main_queue(); // 2.将任务加入队列 dispatch_sync(queue, ^{ NSLog(@"1-----%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"2-----%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"3-----%@", [NSThread currentThread]); }); NSLog(@"syncMain ----- end"); } /** * 异步函数 + 主队列:只在主线程中执行任务 */ - (void)asyncMain { // 1.获得主队列 dispatch_queue_t queue = dispatch_get_main_queue(); // 2.将任务加入队列 dispatch_async(queue, ^{ NSLog(@"1-----%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"2-----%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"3-----%@", [NSThread currentThread]); });
} /** * 同步函数 + 串行队列:不会开启新的线程,在当前线程执行任务。任务是串行的,执行完一个任务,再执行下一个任务 */大概就是默认的状态了,在一条道上一个任务接着一个任务的顺序的执行着; - (void)syncSerial { // 1.创建串行队列 dispatch_queue_t queue = dispatch_queue_create("com.520it.queue", DISPATCH_QUEUE_SERIAL); // 2.将任务加入队列 dispatch_sync(queue, ^{ NSLog(@"1-----%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"2-----%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"3-----%@", [NSThread currentThread]); }); } /** * 异步函数 + 串行队列:会开启新的线程,但是任务是串行的,执行完一个任务,再执行下一个任务 */在子线程上一个接着一个的执行任务; - (void)asyncSerial { // 1.创建串行队列 dispatch_queue_t queue = dispatch_queue_create("com.520it.queue", DISPATCH_QUEUE_SERIAL); // dispatch_queue_t queue = dispatch_queue_create("com.520it.queue", NULL); // 2.将任务加入队列 dispatch_async(queue, ^{ NSLog(@"1-----%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"2-----%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"3-----%@", [NSThread currentThread]); }); } /** * 同步函数 + 并发队列:不会开启新的线程 */ - (void)syncConcurrent { // 1.获得全局的并发队列 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 2.将任务加入队列 dispatch_sync(queue, ^{ NSLog(@"1-----%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"2-----%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"3-----%@", [NSThread currentThread]); }); NSLog(@"syncConcurrent--------end"); } /** * 异步函数 + 并发队列:可以同时开启多条线程 */ - (void)asyncConcurrent { // 1.创建一个并发队列 // label : 相当于队列的名字 并行的队列 串行的队列 // dispatch_queue_t queue = dispatch_queue_create("com.520it.queue", DISPATCH_QUEUE_CONCURRENT); //DISPATCH_QUEUE_SERIAL
//dispatch_queue_create(<#const char * _Nullable label#>, <#dispatch_queue_attr_t _Nullable attr#>)
// 1.获得全局的并发队列:不用自己创建名字都省了 -并发 这个参数是队列的优先级 取值有四种 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 2.将任务加入队列 dispatch_async(queue, ^{ for (NSInteger i = 0; i<10; i++) { NSLog(@"1-----%@", [NSThread currentThread]); } }); dispatch_async(queue, ^{ for (NSInteger i = 0; i<10; i++) { NSLog(@"2-----%@", [NSThread currentThread]); } }); dispatch_async(queue, ^{ for (NSInteger i = 0; i<10; i++) { NSLog(@"3-----%@", [NSThread currentThread]); } }); NSLog(@"asyncConcurrent--------end"); // dispatch_release(queue); } @end
08-掌握-GCD-线程间的通信
在子线程中下载图片,下载完成后回到主线程中显示图片;
// ViewController.m // 08-掌握-GCD-线程间的通信 #import "ViewController.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UIImageView *imageView; //来自storyboard拖拽的控件; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
首先开启异步;--拿到全局并行队列; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 图片的网络路径 NSURL *url = [NSURL URLWithString:@"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg"]; // 加载图片 NSData *data = [NSData dataWithContentsOfURL:url]; // 生成图片 UIImage *image = [UIImage imageWithData:data]; // 回到主线程 dispatch_async(dispatch_get_main_queue(), ^{ self.imageView.image = image; }); }); } @end
09-掌握-GCD的其他常用函数
从网路下载两张图片,合并成一张图片并显示;
下载合成的过程放到子线程中;
// ViewController.m // 09-掌握-GCD的其他常用函数 #import "ViewController.h" #import "XMGPerson.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UIImageView *imageView; /** 图片1 */ @property (nonatomic, strong) UIImage *image1; /** 图片2 */ @property (nonatomic, strong) UIImage *image2; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; XMGPerson *person1 = [[XMGPerson alloc] init]; XMGPerson *person2 = [[XMGPerson alloc] init]; XMGPerson *person3 = [[XMGPerson alloc] init]; XMGPerson *person4 = [[XMGPerson alloc] init]; // XMGPerson *p1 = [[XMGPerson alloc] init]; // NSLog(@"%@", p1.books); // // XMGPerson *p2 = [[XMGPerson alloc] init]; // NSLog(@"%@", p2.books); } void download(void * data) { } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // dispatch_async(<#dispatch_queue_t queue#>, <#^(void)block#>); // dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // dispatch_async_f(queue, NULL, download);
//对应的函数 [self group]; } - (void)group { //拿到全局的并行队列 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 创建一个队列组 dispatch_group_t group = dispatch_group_create(); // 1.下载图片1 dispatch_group_async(group, queue, ^{ // 图片的网络路径 NSURL *url = [NSURL URLWithString:@"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg"]; // 加载图片 NSData *data = [NSData dataWithContentsOfURL:url]; // 生成图片 self.image1 = [UIImage imageWithData:data]; }); // 2.下载图片2 dispatch_group_async(group, queue, ^{ // 图片的网络路径 NSURL *url = [NSURL URLWithString:@"http://pic38.nipic.com/20140228/5571398_215900721128_2.jpg"]; // 加载图片 NSData *data = [NSData dataWithContentsOfURL:url]; // 生成图片 self.image2 = [UIImage imageWithData:data]; }); // 3.将图片1、图片2合成一张新的图片 dispatch_group_notify(group, queue, ^{ // 开启新的图形上下文 UIGraphicsBeginImageContext(CGSizeMake(100, 100)); // 绘制图片 [self.image1 drawInRect:CGRectMake(0, 0, 50, 100)]; [self.image2 drawInRect:CGRectMake(50, 0, 50, 100)]; // 取得上下文中的图片 UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); // 结束上下文 UIGraphicsEndImageContext(); // 回到主线程显示图片 dispatch_async(dispatch_get_main_queue(), ^{ // 4.将新图片显示出来 self.imageView.image = image; }); }); } /** * 快速迭代 */ - (void)apply { dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); NSString *from = @"/Users/xiaomage/Desktop/From"; NSString *to = @"/Users/xiaomage/Desktop/To"; NSFileManager *mgr = [NSFileManager defaultManager]; NSArray *subpaths = [mgr subpathsAtPath:from]; dispatch_apply(subpaths.count, queue, ^(size_t index) { NSString *subpath = subpaths[index]; 取出了数组里的文件 NSString *fromFullpath = [from stringByAppendingPathComponent:subpath]; NSString *toFullpath = [to stringByAppendingPathComponent:subpath]; // 剪切 [mgr moveItemAtPath:fromFullpath toPath:toFullpath error:nil]; NSLog(@"%@---%@", [NSThread currentThread], subpath); }); } /** * 传统文件剪切 */ - (void)moveFile { NSString *from = @"/Users/xiaomage/Desktop/From"; //旧的文件路径 NSString *to = @"/Users/xiaomage/Desktop/To"; //新的文件路径 NSFileManager *mgr = [NSFileManager defaultManager];//拿到文件管理对象; NSArray *subpaths = [mgr subpathsAtPath:from]; //传一个文件夹路径参数,返回的是这个文件夹下的所有文件包括自文件夹和文件;
返回的是一个文件名(字符串)的数组; for (NSString *subpath in subpaths) {//遍历数组里的文件 for 循环
从from这个路径拼接一个文件名; NSString *fromFullpath = [from stringByAppendingPathComponent:subpath]; // 得到完整的路径; NSString *toFullpath = [to stringByAppendingPathComponent:subpath]; // 得到完整的路径;
异步执行多条线程 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 剪切 [mgr moveItemAtPath:fromFullpath toPath:toFullpath error:nil]; //从一个路径去另个路径; }); } } - (void)once { 全局性的整个程序运行过程中只运行一次;运行完后这个代码就等于没有了; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSLog(@"------run");
//这里的面的内容是很安全的多个线程不会同时执行; }); } /** * 延迟执行 */ - (void)delay { NSLog(@"touchesBegan-----"); // [self performSelector:@selector(run) withObject:nil afterDelay:2.0]; // dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // NSLog(@"run-----"); // }); [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:NO]; } - (void)run { NSLog(@"run-----"); } - (void)barrier { dispatch_queue_t queue = dispatch_queue_create("12312312", DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, ^{ NSLog(@"----1-----%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"----2-----%@", [NSThread currentThread]); }); dispatch_barrier_async(queue, ^{//等前面两个任务执行完了在执行这个任务; NSLog(@"----barrier-----%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"----3-----%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"----4-----%@", [NSThread currentThread]); }); } @end
XMGPerson 对象;
// // XMGPerson.h // 09-掌握-GCD的其他常用函数 #import <Foundation/Foundation.h> @interface XMGPerson : NSObject /** 书本 */ @property (nonatomic, strong) NSArray *books; @end
// // XMGPerson.m // 09-掌握-GCD的其他常用函数 #import "XMGPerson.h" @implementation XMGPerson - (NSArray *)books { if (_books == nil) { _books = @[@"1分钟突破iOS开发", @"5分钟突破iOS开发"]; } // static dispatch_once_t onceToken; // dispatch_once(&onceToken, ^{ // _books = @[@"1分钟突破iOS开发", @"5分钟突破iOS开发"]; // }); return _books; } @end