多线程二(GCD)代码笔记
// // TWFXViewController.h // Demo_GCD // // Created by Lion User on 12-12-11. // Copyright (c) 2012年 Lion User. All rights reserved. // #import <UIKit/UIKit.h> @interface TWFXViewController : UIViewController @property (retain, nonatomic) IBOutlet UILabel *outletLabel1; @property (retain, nonatomic) IBOutlet UILabel *outletLabel2; @property (retain, nonatomic) IBOutlet UILabel *outletLabel3; @property (retain, nonatomic) IBOutlet UILabel *outletLabel4; - (IBAction)btnClick4:(UIButton *)sender; - (IBAction)btnClick2:(UIButton *)sender; - (IBAction)btnClick3:(UIButton *)sender; - (IBAction)btnClick:(UIButton *)sender; @end
// // TWFXViewController.m // Demo_GCD // // Created by Lion User on 12-12-11. // Copyright (c) 2012年 Lion User. All rights reserved. // /* GCD(系统管理线程) 简介 使用GCD你不需要编写线程代码,只需定义想要执行的任务,然后添加到适当的 dispatch queue (调度队列)里 GCD会负责创建线程和调度你的任务.系统直接提供线程管理,比应用实现更高效 基于C的执行自定义任务机制,dispatch queue 按先进先出的顺序,串行或并发地执行任务.dispatch queue 分以下三种: serial dispatch queue : 串行调度队列,一次只执行一个任务,直到当前任务完成才开始出列并启动下一个任务 主要用于对特定资源的同步访问.虽然每个串行queue本身每次只能执行一个任务,但各个串行queue之间是并发执行的 concurrent dispatch queue: 也称为 global dispatch queue, 并行调度队列,并发执行一个或多个任务,但启动顺序仍是按照添加到queue的顺序启动 你不能创建并发dispatch queues, 只能使用系统已经定义好了的三个全局并发queues,具体下面说到 main dispatch queue : 全局可用的串行 queue,在应用主线程中执行任务,比如用于刷新UI界面 dispatch queue 相关的技术 Dispatch group : 用于监控一组block对象完成 Dispatch semaphore : 类似于传统的 semaphore (信号量) Dispatch Source : 系统事件异步处理机制 dispatch queue 中的 各个线程,可以通过queue的context指针来共享数据 */ #import "TWFXViewController.h" @interface TWFXViewController () @end @implementation TWFXViewController - (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. } /* 全局并发 Dispatch queue 1. 并发 dispatch queue 可以同时并发执行多个任务,不过并发 queue 仍然按照先进先出的顺序启动任务 2. 并发 queue 同时执行的任务数量会根据应用和系统动态变化,各个因素如:可用核数量 其他进程正在执行的工作数量 其他串行dispatch queue 中的优先任务的数量等 3. 系统会给每个应用程序提供三个并发 dispatch queue,全局共享,三个queue的唯一区别在于优先级不同 */ - (IBAction)btnClick4:(UIButton *)sender { /* 获取全局并发 dispatch queue : dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 第一个参数表示 queue 的优先级,这里获取默认优先级的那个queue,也可以获取高/低优先级的那个,把 DEFAULT 换成 HIGH 或 LOW 就行了 第二个参数表示 ? */ dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //把一个block加入到全局并发调度队列里 dispatch_async(aQueue, ^(void) { for (int i = 0; i < 1000; i++) { //把block同步添加到主线程里,这样子,demo queue 就会暂停等这个block执行完成才继续执行 dispatch_sync(dispatch_get_main_queue(), ^(void) { NSString *text = [NSString stringWithFormat:@"%d", i]; self.outletLabel3.text = text; }); } }); //把另一个block加入到全局并发调度队列里.这个block和上面那个block会并发执行 dispatch_async(aQueue, ^(void){ for (int i = 0; i < 1000; i++) { //把block同步添加到主线程里,这样子,demo queue 就会暂停等这个block执行完成才继续执行 dispatch_sync(dispatch_get_main_queue(), ^(void) { NSString *text = [NSString stringWithFormat:@"%d", i]; self.outletLabel4.text = text; }); } }); } /* 串行 Dispatch queue 1. 串行 queue 每次只能执行一个任务,可以使用它来代替锁,保护共享资源或可变的数据结构,串行queue确保任务按可预测的顺序执行(这是比锁好的地方) 2. 必须显式创建和管理所有你使用的串行queue(数目任意) */ - (IBAction)btnClick2:(UIButton *)sender { /* 使用 dispatch_queue_create() 方法来创建串行queue 第一个参数表示 queue 的名字, 第二个参数表示 queue 的一组属性(保留给将来使用) */ dispatch_queue_t queue = dispatch_queue_create("demo queue", NULL); /* 异步调度和同步调度 异步调度 dispatch_async : 把一个任务添加到某queue后就马上离开,而不管任务在那个queue里的执行状态 同步调度 dispatch_sync : 把一个任务添加到某queue后,等这个任务完成,调用线程才继续执行.尼玛,坑爹啊 所以,异步调度和同步调度的区别不在于被添加的任务怎样执行,而在于调用线程是否等待任务执行完 */ //把block异步添加到上面创建的名为 demo queue 的调度队列里 dispatch_async(queue, ^(void){ for (int i = 0; i < 1000; i++) { // sleep(1); // printf("a%d\t",i); //把block同步添加到主线程里,这样子,demo queue 就会暂停等这个block执行完成才继续执行 dispatch_sync(dispatch_get_main_queue(), ^(void) { NSString *text = [NSString stringWithFormat:@"%d", i]; self.outletLabel1.text = text; // printf("b%d\n",i); }); } }); //因为 demo queue 是串行调度队列,所以等上面那个block执行完,下面这个block才会开始 dispatch_async(queue, ^(void){ for (int i = 0; i < 1000; i++) { dispatch_sync(dispatch_get_main_queue(), ^(void) { self.outletLabel2.text = [NSString stringWithFormat:@"%d", i]; }); } }); //xxxxx_create 的object对象要对应 xxxxx_release ? dispatch_release(queue); //这个循环都会卡屏幕~~~ // for (int i = 0; i < 100000; i++) { // self.outletLabel1.text = [NSString stringWithFormat:@"%d", i]; // printf("%d\n", i); // } } -(void)test:(NSString *)data { self.outletLabel1.text = data; } /* dispatch_group 可以把一组task放到一个group里,等group里的所有task都执行完后再继续运行 */ - (IBAction)btnClick3:(UIButton *)sender { //重置label2的text self.outletLabel2.text = @"begin"; //获取一个全局并发 调度队列 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //创建一个 dispatch group dispatch_group_t group = dispatch_group_create(); //定义 task1 dispatch_block_t task1 = ^(void){ for (int i = 0; i < 300; i++) { dispatch_sync(dispatch_get_main_queue(), ^(void){ self.outletLabel3.text = [NSString stringWithFormat:@"%d", i]; }); } }; //定义task2 dispatch_block_t task2 = ^(void){ for (int i = 0; i < 300; i++) { dispatch_sync(dispatch_get_main_queue(), ^(void){ self.outletLabel4.text = [NSString stringWithFormat:@"%d", i]; }); } }; //把task1关联到 queue 和group dispatch_group_async(group, queue, task1); //把task2关联到 queue和group dispatch_group_async(group, queue, task2); //等group里的task都执行完后执行notify方法里的内容,相当于把wait方法及之后要执行的代码合到一起了 dispatch_group_notify(group, dispatch_get_main_queue(), ^(void){ self.outletLabel2.text = @"done!"; }); //XXX_create创建,就需要对应的 XXX_release() dispatch_release(group); } /* dispatch source */ - (IBAction)btnClick:(UIButton *)sender { } - (void)dealloc { [_outletLabel1 release]; [_outletLabel2 release]; [_outletLabel3 release]; [_outletLabel4 release]; [super dealloc]; } @end
花开花谢春不管,水暖水寒鱼自知.