實際開發中多線程的使用時非常常見的,多線程是指程序中包含多個執行流,即在一個程序中可以同時運行多個不同的線程來執行不同的任務,也就是說允許單個程序創建多個并行執行的線程來完成各自的任務。可以提高CPU的利用率。在多線程程序中,一個線程必須等待的時候,CPU可以運行其它的線程而不是等待,這樣就大大提高了程序的效率。
本文介紹關于多線程常用的,也是最基本的使用方法。
1.NSObject自帶的多線程
首先創建一個imageView和button:
(文本創建較多按鈕暫時用數字后綴代替,實際編程中盡量避免使用數字)
@property(nonatomic, strong)UIImageView *imageView;
@property(nonatomic, strong)UIButton *button2;
初始化imageView和相應的button:
self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(107,
500, 200, 200)];
self.imageView.backgroundColor = [UIColor yellowColor];
[self.view addSubview:self.imageView];
self.button2 = [UIButton buttonWithType:UIButtonTypeCustom];
self.button2.frame = CGRectMake(107, 10 + 40, 200, 30);
self.button2.backgroundColor = [UIColor blueColor];
[self.button2 setTitle:@"自帶的多線程" forState:UIControlStateNormal];
[self.button2 addTarget:self action:@selector(didClickedButton2:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.button2];
執行方法
//自帶的多線程
- (void)didClickedButton2:(UIButton *)button2
{
//在多線程里面執行某個方法
[self performSelectorInBackground:@selector(getImageByURL) withObject:nil];
}
//這個方法會在分支線程里執行(非主線程)
- (void)getImageByURL
{
//1.在分支線程里請求數據
self.data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://pic14.nipic.com/20110522/7411759_164157418126_2.jpg"]];
//2.回到主線程更新UI
[self performSelectorOnMainThread:@selector(updataUI) withObject:nil waitUntilDone:YES];
}
//3.回主線程更新UI方法
- (void)updataUI
{
self.imageView.image = [UIImage imageWithData:self.data];
}
點擊按鈕
2.自動分配線程
@property(nonatomic, strong)UIButton *button3;
self.button3 = [UIButton buttonWithType:UIButtonTypeCustom];
self.button3.frame = CGRectMake(107, 10 + 40 + 40, 200, 30);
self.button3.backgroundColor = [UIColor blueColor];
[self.button3 setTitle:@"自動分配" forState:UIControlStateNormal];
[self.button3 addTarget:self action:@selector(didClickedButton3:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.button3];
//自動分配線程
- (void)didClickedButton3:(UIButton *)button3
{
[NSThread detachNewThreadSelector:@selector(getImageByURL) toTarget:self withObject:nil];
}
點擊按鈕
3.手動分配線程
@property(nonatomic, strong)UIButton *button4;
self.button4 = [UIButton buttonWithType:UIButtonTypeCustom];
self.button4.frame = CGRectMake(107, 10 + 40 + 40 + 40, 200, 30);
self.button4.backgroundColor = [UIColor blueColor];
[self.button4 setTitle:@"手動分配" forState:UIControlStateNormal];
[self.button4 addTarget:self action:@selector(didClickedButton4:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.button4];
//手動分配線程
- (void)didClickedButton4:(UIButton *)button4
{
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(getImageByURL) object:nil];
//手動開啟線程
[thread start];
//讓線程延遲3秒
[NSThread sleepForTimeInterval:3];
}
點擊按鈕視圖會在3秒后呈現
4.NSIncationOperation 方法:
按鈕按以上依次創建,這里只寫方法
#pragma mark -- NSIncationOperation 方法:
- (void)didClickedButton5:(UIButton *)button5
{
//這個類是NSOperation的一個子類
NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(getImageByURL) object:nil];
//手動開啟
[invocationOperation start];
}
點擊按鈕
5.NSBlockOperation方法
pragma mark -- NSBlockOperation方法
- (void)didClickedButton6:(UIButton *)button6
{
__weak ViewController *blockVC = self;
//這個類也是NSOperation的一個子類
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
//在分支線程里請求數據
blockVC.data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://pic14.nipic.com/20110522/7411759_164157418126_2.jpg"]];
//回主線程更新UI
[self performSelectorOnMainThread:@selector(updataUI) withObject:nil waitUntilDone:YES];
}];
//手動開啟
[blockOperation start];
}
點擊按鈕
6.線程隊列
- (void)didClickedButton7:(UIButton *)button7
{
//創建隊列對象
NSOperationQueue *queue = [NSOperationQueue new];
//設置最大并發數
queue.maxConcurrentOperationCount = 1;
//向隊列中添加任務
for (NSInteger i = 0; i < 10; i++) {
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"當前線程 : %@ 是否是主線程:%d : %ld",[NSThread currentThread], [NSThread isMainThread], i );
}];
//將任務添加到線程隊列中
[queue addOperation:blockOperation];
}
}
點擊按鈕 打印出:
7.GCD串行
- (void)didClickedButton8:(UIButton *)button8
{
//方法一:
獲取程序的主隊列:
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
NSLog(@"我是第一個任務,是否是主線程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
NSLog(@"我是第二個任務,是否是主線程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
NSLog(@"我是第三個任務,是否是主線程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
NSLog(@"我是第四個任務,是否是主線程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
NSLog(@"我是第五個任務,是否是主線程:%d",[NSThread isMainThread]);
});
//方法二:
//創建一個串行隊列
//參數一:隊列的名字(蘋果推薦以反域名的形式書寫)
//參數二:隊列的類型(串行或者并行)
dispatch_queue_t queue = dispatch_queue_create("com.alibaba.queue1", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"我是第一個任務,是否是主線程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
NSLog(@"我是第二個任務,是否是主線程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
NSLog(@"我是第三個任務,是否是主線程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
NSLog(@"我是第四個任務,是否是主線程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
NSLog(@"我是第五個任務,是否是主線程:%d",[NSThread isMainThread]);
});
}
點擊按鈕 打印出:
8.延時執行
- (void)didClickedButton9:(UIButton *)button9
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.view.backgroundColor = [UIColor redColor];
});
}
點擊按鈕
9.只執行一次
- (void)didClickedButton10:(UIButton *)button10
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"我只走一次");
});
}
點擊按鈕 打印出:
10.多次執行
- (void)didClickedButton11:(UIButton *)button11
{
dispatch_queue_t queue = dispatch_queue_create("com.lanou3g.test", DISPATCH_QUEUE_CONCURRENT);
dispatch_apply(3, queue, ^(size_t index) {
NSLog(@"我走了 %ld 累死了都 ", index);
});
}
點擊按鈕 打印出:
11.線程互斥
這里舉車站買票例子
- (void)didClickedButton12:(UIButton *)button12
{
self.count = 100; //票的總數
dispatch_queue_t queue = dispatch_queue_create("com.123.6.sellTicket", DISPATCH_QUEUE_CONCURRENT);
//創建線程鎖對象
NSLock *lock = [NSLock new];
//開辟10個買票窗口
for (NSInteger i = 0; i < 10; i++) {
dispatch_async(queue, ^{
[lock lock]; //加鎖
//每個窗口可以賣10張票
for (NSInteger j = 0; j < 10; j++) {
NSLog(@"我買到了第 %ld 張票", self.count);
self.count--;
}
[lock unlock]; //解鎖
});
}
}
點擊按鈕 打印出:
每個不同按鈕都有各自的方法,感興趣的小伙伴可以試試哦
使用多線程的好處:
可以使CPU多個核同時使用,令計算機效率更高效化,以前單核的機器,同時有兩個線程在運行時,是先把其中某線程先執行的形式,這樣無疑延長了計算所有的時間,多核的情況下,一線程可以交給一個核去處理,另一個線程可以交給另一個核去處理,這個,計算機的資源利用就大大升高.減少用戶等待時間。
什么時候使用多線程:
按生活原理.當你在吃飯的時候看電視,是不是大腦在同時控制你進行著兩種工作?同理,計算機也一樣,比如,軟件在后臺處理文件的時候,同時又顯示給用戶看與后臺處理無關的內容,這時候,我們總不能等后臺處理完了,執行顯示.這時候多線程的優勢就很明顯了.
多線程主要用于計算機同時執行多個任務,而多個任務之間的執行是不互相影響的
希望大家在實際開發中熟練使用多線程,大家一同學習!!!