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