ios学习:多线程一(简单使用)
xib界面 就放6个UIButton,并将他们的Touch Up Inside 事件与 .h文件里的IBAction关联起来;另外还有两个UILabel,把他们的Outlet与 .h文件里的输出口关联起来就行了.
1 #import <UIKit/UIKit.h> 2 #import "TWFXAppDelegate.h" 3 4 @interface TWFXViewController : UIViewController 5 { 6 NSOperationQueue *operationQueue; 7 } 8 9 @property (retain, nonatomic) IBOutlet UILabel *outletData; 10 11 @property (retain, nonatomic) IBOutlet UILabel *outletLabel; 12 - (IBAction)thread_NSObject:(UIButton *)sender; 13 - (IBAction)thread_Operation:(UIButton *)sender; 14 - (IBAction)thread_detch:(UIButton *)sender; 15 - (IBAction)thread_alloc:(UIButton *)sender; 16 - (IBAction)thread_OperationBlocks:(UIButton *)sender; 17 - (IBAction)thread_GCD:(UIButton *)sender; 18 @end
1 // 2 // TWFXViewController.m 3 // DemoMultiThread 4 // 5 // Created by Lion User on 12-12-6. 6 // Copyright (c) 2012年 Lion User. All rights reserved. 7 // 8 9 #import "TWFXViewController.h" 10 11 @interface TWFXViewController () 12 13 @end 14 15 @implementation TWFXViewController 16 @synthesize outletLabel = _outletLabel; 17 - (void)viewDidLoad 18 { 19 [super viewDidLoad]; 20 // Do any additional setup after loading the view, typically from a nib. 21 22 //创建线程队列(线程池) 23 operationQueue = [[NSOperationQueue alloc] init]; 24 25 /* 26 设置线程池中的线程数,也就是并发操作数,默认是-1,也就是不限数量,同时运行队列中的所有操作 27 */ 28 [operationQueue setMaxConcurrentOperationCount:2]; 29 30 31 32 self.outletLabel.textAlignment = NSTextAlignmentCenter; 33 self.outletLabel.text = @"test"; 34 } 35 36 - (void)didReceiveMemoryWarning 37 { 38 [super didReceiveMemoryWarning]; 39 // Dispose of any resources that can be recreated. 40 self.outletLabel = nil; 41 } 42 43 - (void)dealloc { 44 [_outletLabel release]; 45 [operationQueue release]; 46 [_outletData release]; 47 [super dealloc]; 48 } 49 50 51 52 /* 53 不显示创建线程的方法 54 创建后台线程,方法1 55 这种方式,在方法被调用时,会立马创建一个后台线程并运行 56 */ 57 - (IBAction)thread_NSObject:(UIButton *)sender { 58 59 [self performSelectorInBackground:@selector(doSomething:) withObject:@"performSelectorInBackground"]; 60 } 61 62 63 64 /* 65 NSThread 类----类方法 66 创建后台线程,方法3 67 这种方式,在方法被调用时,会立马创建一个后台线程并运行 68 和方法1一样 69 70 NSThread 类 量级比较轻,但需要自己管理线程的生命周期 和 线程同步 等 71 线程的同步对数据的加锁需要一定的开销 72 */ 73 - (IBAction)thread_detch:(UIButton *)sender { 74 75 [NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:@"detachNewThreadSelector"]; 76 } 77 78 79 /* 80 NSThread类----实例方法 81 创建后台线程,方法4 82 这种方式,虽然alloc init 了,但需要手动调用 start 方法来启动线程,在启动之前,可以对线程进行一些设置,比如stack大小 优先级等 83 */ 84 - (IBAction)thread_alloc:(UIButton *)sender { 85 86 NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(doSomething:) object:@"NSThread alloc inittWithTarget"]; 87 88 [thread setName:@"thread_alloc"]; //设置线程名字 89 [thread setStackSize:100];//设置stack大小 90 [thread setThreadPriority:10.f]; //设置线程优先级 91 92 [thread start];//启动线程 93 } 94 95 96 97 98 99 100 /* 101 NSOperation类 --- NSInvocastionOperation 102 不需要关心 线程管理 数据同步 等问题,把焦点放在需要实现的地方 103 创建后台线程,方法2 104 NSOperation 是抽象类,需要自定义其子类,或者使用他的两个一经实现了的子列:NSInvocationOperation NSBlockOperation 105 然后把线程添加到线程队列里 106 107 */ 108 - (IBAction)thread_Operation:(UIButton *)sender { 109 110 NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doSomething:) object:@"NSInvocationOperation"]; 111 112 [operationQueue addOperation:op];//把线程加到线程队列里,然后线程立马启动 113 } 114 115 116 117 /* 118 NSOperation类 --- NSBlockOperation 119 可以添加多个block,执行顺序呢? 120 */ 121 - (IBAction)thread_OperationBlocks:(UIButton *)sender { 122 123 NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^(void){ 124 125 for (int i = 0; i < 1000; i++) { 126 127 NSString *text = [[[NSString alloc] initWithFormat:@"%d", i] autorelease]; 128 129 130 /* 131 在这里不能通过 self XXXX 来操作界面,要通过调用主线程的方法来实现,把要对UI的操作放在主线程的方法里 132 */ 133 // self.outletLabel.text = text; 134 [self performSelectorOnMainThread:@selector(updateUI:) withObject:text waitUntilDone:YES]; 135 136 } 137 }]; 138 139 140 [op addExecutionBlock:^(void){ 141 142 for (int i = 0; i < 1000; i++) { 143 144 NSString *text = [[[NSString alloc] initWithFormat:@"%d", i] autorelease]; 145 146 147 /* 148 在这里不能通过 self XXXX 来操作界面,要通过调用主线程的方法来实现,把要对UI的操作放在主线程的方法里 149 */ 150 // self.outletLabel.text = text; 151 [self performSelectorOnMainThread:@selector(updateLabel:) withObject:text waitUntilDone:YES]; 152 153 } 154 }]; 155 156 157 [operationQueue addOperation:op]; 158 159 } 160 161 162 163 164 /* 165 GCD: 以优化的应用程序支持多核心处理器和其他的对称多处理系统的系统 166 工作原理:让程序平行排队的特定任务根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务,一个任务可以是一个函数(function) 或者是一个block 167 GCD中的队列采用FIFO(先进先出)机制,保证先进来的任务得以优先执行.(优先开始不代表早点结束) 168 GCD里的队列(线程池?)分下面三种: 169 Serial:private dispatch queues,同时只执行一个任务,通常用于同步访问特定的资源或数据 170 Concurrent: global dispatch queue;可以并发执行多个任务,执行完成的顺序是随机的. 171 系统给每个应用程序提供三个concurrent dispatch queues,这三个并发调度队列是全局的,只有优先级的不同 172 Main dispatch queue: 全局可用的serial queue,是在应用程序主线程上执行任务的.就是UI线程? 173 */ 174 - (IBAction)thread_GCD:(UIButton *)sender { 175 176 177 //dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0):获取一个并发的全局队列,把block加到队列里 178 179 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { 180 181 //获取主线程队列,把一个block加到队列里 182 dispatch_async(dispatch_get_main_queue(), ^(void) { 183 184 self.outletData.text = @"gcd!"; 185 186 } ); 187 188 for (int i = 0; i < 1000; i++) { 189 190 NSString *text = [[[NSString alloc] initWithFormat:@"%d", i]autorelease]; 191 192 dispatch_async(dispatch_get_main_queue(), ^(void){ 193 194 self.outletLabel.text = text; 195 }); 196 } 197 }); 198 199 dispatch_async(dispatch_get_main_queue(), ^(void){ 200 201 self.outletData.text = @"gcd had changed"; 202 }); 203 204 } 205 206 207 /* 208 该方法被后台线程调用,在这里不能操作主线程的东西,例如UI线程 209 要想操作UI,得调用主线程的方法来操作 210 作为多线程的回调方法,需要自行管理内存的释放,否则会引起泄露 211 */ 212 -(void)doSomething:(id)data 213 { 214 @autoreleasepool { 215 216 [self performSelectorOnMainThread:@selector(updateLabel:) withObject:data waitUntilDone:YES]; 217 for (int i = 0; i < 1000; i++) { 218 219 NSString *text = [[[NSString alloc] initWithFormat:@"%d", i] autorelease]; 220 221 222 /* 223 线程间通信:通知主线程 224 在这里不能通过 self XXXX 来操作界面,要通过调用主线程的方法来实现,把要对UI的操作放在主线程的方法里 225 */ 226 // self.outletLabel.text = text; 227 [self performSelectorOnMainThread:@selector(updateUI:) withObject:text waitUntilDone:YES]; 228 229 } 230 231 data = @"value had changed!"; 232 [self performSelectorOnMainThread:@selector(updateLabel:) withObject:data waitUntilDone:YES]; 233 234 } 235 236 } 237 238 239 /* 240 刷新界面,作为回调函数被调用 241 */ 242 -(void)updateUI:(NSString *) text 243 { 244 // self.outletLabel.textAlignment = NSTextAlignmentCenter; 245 self.outletLabel.text = text; 246 } 247 248 249 -(void)updateLabel:(NSString *) data 250 { 251 self.outletData.text = data; 252 } 253 254 255 @end