目錄
- pthread
- NSThread
- GCD
- NSOperation
- 線程鎖
- 線程通訊
| 多線程實(shí)現(xiàn)方案 | 特點(diǎn) | 語言 | 頻率 | 線程生命周期
| ------------------------------
| pthread | 1、一套通用的多線程API 2、適用于Unix\Linux\Windows等系統(tǒng) 3八孝、跨平臺(tái)\可移植 4川尖、使用難度大 | c語言 | 幾乎不用 | 由程序員進(jìn)行管理
| NSThread | 1、使用更加面向?qū)ο?2馍佑、簡單易用,可直接操作線程對(duì)象 | OC語言 | 偶爾使用 | 由程序員進(jìn)行管理
| GCD | 1、旨在替代NSThread等線程技術(shù) 2礁叔、充分利用設(shè)備的多核(自動(dòng)) | C語言 | 經(jīng)常使用 | 自動(dòng)管理
| NSOperation | 1、基于GCD(底層是GCD) 2迄薄、比GCD多了一些更簡單實(shí)用的功能 3琅关、使用更加面向?qū)ο?| OC語言 | 經(jīng)常使用 | 自動(dòng)管理
1. pthread
pthread是一套C語言的多線程API 使用難度比較大 需要程序員手動(dòng)管理線程的生命周期 能夠跨平臺(tái)/可移植 能夠在UNIX/LINX/Windows 下運(yùn)行
2. NSThread
是一套OC框架 使用更加面向?qū)ο?簡單易用,可直接操作線程對(duì)象 偶爾使用
需要程序員手動(dòng)管理線程的聲明周期
一般用來查看當(dāng)前線程是否是主線程:
=1 當(dāng)前線程是主線程,!=1 當(dāng)前線程是在子線程
[NSThread currentThread]獲取的當(dāng)前的線程
[NSThread isMainThread]判斷當(dāng)前線程是否是主線程。
主線程的number==1讥蔽,{number = 1, name = main}
- 使用類方法開辟子線程
[NSThread detachNewThreadSelector:@selector(print1) toTarget:self withObject:nil] ;
- 創(chuàng)建對(duì)象 開辟子線程
NSThread *thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(print1) object:nil];
//開啟子線程 并執(zhí)行任務(wù)
[thread1 start];
- 使用NSObject提供的方法
[self performSelector:@selector(print1) withObject:nil];
3. GCD
旨在代替NSThread多線程技術(shù),充分利用設(shè)備的多核
也是一套基于C語言的API 不需要程序員手動(dòng)管理線程的聲明周期 經(jīng)常使用.
應(yīng)用:
- 延時(shí)操作
- 一次性操作-單例
- 計(jì)時(shí)器
4. NSOperation
是一套OC的API,是對(duì)GCD的封裝 使用更加面向?qū)ο? 不需要程序員手動(dòng)管理線程的聲明周期
比GCD多一些更加簡單實(shí)用的功能 也是經(jīng)常使用 特別是在iOS4以后
- 使用block創(chuàng)建任務(wù)
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
}];
- 使用NSInvocationOperation 創(chuàng)建任務(wù)
NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(action) object:nil];
//創(chuàng)建任務(wù)隊(duì)列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//控制開辟線程的個(gè)數(shù)
queue.maxConcurrentOperationCount = 1;
//添加任務(wù)
[queue addOperation:operation1];
5. iOS多線程中的鎖
- 互斥鎖:@synchronized 是為了保證其中代碼只有一天線程來執(zhí)行
- atomic(原子屬性): 默認(rèn)是線程安全的 當(dāng)多個(gè)線程寫入屬性時(shí),保證同一時(shí)間只有一條線程能夠執(zhí)行寫入操作
6. 線程間的通訊
- 1.在NSThread中線程間的通訊
//在指定線程上執(zhí)行操作
[self performSelector:@selector(run) onThread:thread withObject:nil waitUntilDone:YES];
//在主線程上執(zhí)行操作
[self performSelectorOnMainThread:@selector(run) withObject:nil waitUntilDone:YES];
//在當(dāng)前線程執(zhí)行操作
[self performSelector:@selector(run) withObject:nil];
- 等到兩張圖片加載完成后一起刷新
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UIImage *image1 = [self loadImage:imgUrl1];
UIImage *image2 = [self loadImage:imgUrl2];
dispatch_async(dispatch_get_main_queue(), ^{
self.imageview1.image = image1;
self.imageView2.image = image2;
});
});
異步并行涣易,不需要理會(huì)各自圖片加載的先后問題,完成加載圖片刷新UI即可。也是以加載兩張圖片為例
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{ dispatch_group_t group = dispatch_group_create();
__block UIImage *image1 = nil;
__block UIImage *image2 = nil;
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
image1 = [self loadImage:imgUrl1];
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
image2 = [self loadImage:imgUrl2];
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
self.imageview1.image = image1;
self.imageView2.image = image2;
});
});
- NSOperation
// 1.創(chuàng)建一個(gè)新的隊(duì)列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 2.添加任務(wù)(操作)
[queue addOperationWithBlock:^{
// 2.1在子線程中下載圖片
NSURL *url = [NSURL URLWithString:url];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
// 2.2回到主線程更新UI
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.imageView.image = image;
}];
}];