多線程
先在storyboard上繪制兩顆按鈕,并且綁定事件稀余。
先看下面一段代碼:
- (IBAction)blueButtonClicked:(UIButton *)sender {
NSLog(@"藍(lán)色按鈕任務(wù)開(kāi)始執(zhí)行");
// 模擬任務(wù)需要執(zhí)行5s
sleep(5);
NSLog(@"藍(lán)色按鈕任務(wù)已經(jīng)完成");
}
- (IBAction)yellowButtonClicked:(UIButton *)sender {
NSLog(@"黃色按鈕任務(wù)完成");
}
點(diǎn)擊藍(lán)色按鈕之后就會(huì)卡在那里了国葬,如果此時(shí)點(diǎn)擊黃色按鈕,不能看到NSLog打印的語(yǔ)句未辆,但事實(shí)上任務(wù)已經(jīng)執(zhí)行了窟绷,必須等到藍(lán)色按鈕執(zhí)行的事件執(zhí)行完之后控制臺(tái)才能打印出來(lái)。
多線程
- (void) bar:(UIButton *)sender{
sender.enabled = YES;
[sender setTitle:@"藍(lán)色" forState:UIControlStateNormal];
}
- (IBAction)yellowButtonClicked:(UIButton *)sender {
NSLog(@"黃色按鈕任務(wù)完成");
}
- 第一種方式
- (IBAction)blueButtonClicked:(UIButton *)sender {
[sender setTitle:@"正在執(zhí)行..." forState:UIControlStateNormal];
sender.enabled = NO;
// 提示:對(duì)于那些耗時(shí)間的任務(wù)基本上都應(yīng)該放到其它的執(zhí)行線程中
// 不要阻塞主線程的執(zhí)行 否則界面會(huì)出現(xiàn)卡頓或假死現(xiàn)象
// 模擬任務(wù)需要執(zhí)行5s
//sleep(5);
//NSLog(@"藍(lán)色按鈕任務(wù)已經(jīng)完成");
[self performSelectorInBackground:@selector(foo:) withObject:sender];
}
- (void) foo:(UIButton *)sender{
sleep(5);
NSLog(@"藍(lán)色按鈕任務(wù)已經(jīng)完成");
// 執(zhí)行完之后要恢復(fù)按鈕的狀態(tài)
//sender.enabled = YES;
//[sender setTitle:@"藍(lán)色" forState:0];
// 提示:刷新視圖界面要回到主線程執(zhí)行,如果直接在這里執(zhí)行 可能會(huì)失效
[self performSelectorOnMainThread:@selector(bar:) withObject:sender waitUntilDone:YES];
}
- 第二種方式1
- (IBAction)blueButtonClicked:(UIButton *)sender {
[sender setTitle:@"正在執(zhí)行..." forState:UIControlStateNormal];
sender.enabled = NO;
[NSThread detachNewThreadSelector:@selector(foo:) toTarget:self withObject:sender];
}
- (void) foo:(UIButton *)sender{
sleep(5);
NSLog(@"藍(lán)色按鈕任務(wù)已經(jīng)完成");
[self performSelectorOnMainThread:@selector(bar:) withObject:sender waitUntilDone:YES];
}
- 第二種方式2
- (IBAction)blueButtonClicked:(UIButton *)sender {
[sender setTitle:@"正在執(zhí)行..." forState:UIControlStateNormal];
sender.enabled = NO;
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(foo:) object:sender];
[thread start];
//[thread cancel];// 如果加上這句任務(wù)取消
// 如果線程已經(jīng)開(kāi)始執(zhí)行則無(wú)法取消
// 下面的方法任務(wù)不能取消
//[thread start];
//sleep(1);
//[thread cancel];
}
- (void) foo:(UIButton *)sender{
// 休眠和退出都是只有正在執(zhí)行的線程可以調(diào)用的方法
// 因此在設(shè)計(jì)上這兩個(gè)方法都是類(lèi)方法而不是對(duì)象方法
//[NSThread exit];
sleep(5);
NSLog(@"藍(lán)色按鈕任務(wù)已經(jīng)完成");
[self performSelectorOnMainThread:@selector(bar:) withObject:sender waitUntilDone:YES];
}
- 第三種方式
- (IBAction)blueButtonClicked:(UIButton *)sender {
[sender setTitle:@"正在執(zhí)行..." forState:UIControlStateNormal];
sender.enabled = NO;
// 創(chuàng)建一個(gè)操作對(duì)象(將該操作放到一個(gè)隊(duì)列中去執(zhí)行)
NSOperation *op = [NSBlockOperation blockOperationWithBlock:^{
[self foo:sender];
}];
// 創(chuàng)建一個(gè)并發(fā)隊(duì)列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 設(shè)置最大并發(fā)數(shù)
queue.maxConcurrentOperationCount = 5;
// 向隊(duì)列中添加一個(gè)操作
[queue addOperation:op];
}
- (void) foo:(UIButton *)sender{
sleep(5);
NSLog(@"藍(lán)色按鈕任務(wù)已經(jīng)完成");
// 創(chuàng)建一個(gè)操作對(duì)象
NSOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(bar:) object:sender];
// 向主線程操作隊(duì)列中添加操作對(duì)象(操作放到主線程中執(zhí)行)
[[NSOperationQueue mainQueue] addOperation:op];
}
- 第四種方法
- (IBAction)blueButtonClicked:(UIButton *)sender {
[sender setTitle:@"正在執(zhí)行..." forState:UIControlStateNormal];
sender.enabled = NO;
// GCD - Grand Center Dispatch
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(5);
NSLog(@"藍(lán)色按鈕任務(wù)已經(jīng)完成");
dispatch_async(dispatch_get_main_queue(), ^{
sender.enabled = YES;
[sender setTitle:@"藍(lán)色" forState:UIControlStateNormal];
});
});
}