一? pthread :?
/*
參數(shù):
1.線程代號的地址
2.線程的屬性
3.調(diào)用函數(shù)的指針
4.傳遞給函數(shù)的參數(shù)
返回值:
- 如果是 0, 表示正確
- 如果是非0,表示錯誤碼
void *--(*)--(void *)
返回值--(函數(shù)指針)--(參數(shù))
void *? 相當(dāng)于 OC中的id
*/
-(void)pthreadDemo{
pthread_t threadID;
NSString * str = @"hello 老王";
/*
- 在 ARC 開發(fā)中, 如果遇到 OC和C 語言中相同數(shù)據(jù)類型進(jìn)行轉(zhuǎn)換,需要使用__bridge "橋接"
- 在 MRC 開發(fā)中,不需要橋接
在 OC 中,如果是ARC開發(fā),編譯器會在編譯的時(shí)候,自動根據(jù)代碼結(jié)構(gòu),添加 retain , release, autorelease
ARC 只負(fù)責(zé) OC部分的代碼,不負(fù)責(zé)C的代碼. 如果C的代碼里面出現(xiàn)了 retain/create/copy 字樣的函數(shù),都需要release
*/
int result = pthread_create(&threadID, NULL, &demo, (__bridge void *)(str));
if (result == 0) {
for (int i? = 0; i < 20; i++) {
NSLog(@"OK!");
}
}else{
NSLog(@"error %d",result);
}
}
void * demo(void *param){
NSString * sss = (__bridge NSString *)(param);
NSLog(@"%@---%@",[NSThread currentThread],sss);
return NULL;
}
一 ?NSThread
oc語言需要程序員手動管理線程
//創(chuàng)建線程 開辟一個(gè)子線程 常用創(chuàng)建方法
?1 ?NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(demo:) object:@"thread"];
//啟動線程
[thread start];
//創(chuàng)建以后立即開啟
2 ?[NSThread detachNewThreadSelector:@selector(demo:) toTarget:self withObject:@"Detach"];
//常用的方法
3 ? [self performSelectorInBackground:@selector(longOperation) withObject:nil];
延時(shí)操作
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];
[NSThread sleepForTimeInterval:2.0];
殺死線程
//一旦強(qiáng)行終止線程,后續(xù)的所有的代碼都不會執(zhí)行
//注意:在終止線程之前,應(yīng)該注意釋放之前分配的對象!否則出現(xiàn)內(nèi)存泄露!
?4 ?[NSThread exit];
二 優(yōu)先級屬性
/*優(yōu)先級
* 優(yōu)先級只能保證 CPU 調(diào)度的可能性會高!
* 多線程的目的: 將耗時(shí)的操作放在后臺,不阻塞主線程和用戶的交互!
* 建議: 盡量不要修改 優(yōu)先級!
* "優(yōu)先級翻轉(zhuǎn)"
* 在多線程開發(fā)中,不要相信你看到的結(jié)果!!一定要理性的(冷靜)分析!!
*/
t2.threadPriority = 0.1;
三 ?資源共享
@synchronized
//參數(shù):就是能夠加鎖的任意 NSOjbect 對象
//局部變量: 每個(gè)線程單獨(dú)擁有的,無法鎖住!!
//注意: 鎖一定要是所有線程共享的對象!!
@synchronized (<#token#>) {
<#statements#>
//互斥鎖 - 保證鎖內(nèi)的代碼,同一時(shí)間,只有一條線程能夠執(zhí)行!!
//互斥鎖它的范圍,應(yīng)該盡量小,鎖范圍越大,效率越低!
}
三 GCD 相關(guān)用法
1. 什么是GCD
全稱是Grand Central Dispatch,可譯為“牛逼的中樞調(diào)度器”
純C語言,提供了非常多強(qiáng)大的函數(shù)
2. GCD的優(yōu)勢
GCD是蘋果公司為多核的并行運(yùn)算提出的解決方案
GCD會自動利用更多的CPU內(nèi)核(比如雙核险污、四核 為以后蘋果公司推出多核提供兼容)
GCD會自動管理線程的生命周期(創(chuàng)建線程、調(diào)度任務(wù)、銷毀線程)
程序員只需要告訴GCD想要執(zhí)行什么任務(wù)太颤,不需要編寫任何線程管理代碼
3.GCD中有2個(gè)核心概念
任務(wù):執(zhí)行什么操作
隊(duì)列:用來存放任務(wù)
GCD的使用就2個(gè)步驟
定制任務(wù)
確定想做的事情
將任務(wù)添加到隊(duì)列中
GCD會自動將隊(duì)列中的任務(wù)取出,放到對應(yīng)的線程中執(zhí)行
任務(wù)的取出遵循隊(duì)列的FIFO原則:先進(jìn)先出纯衍,后進(jìn)后出
4 GCD常用方法
1. 延時(shí)操作
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
});
2 一次執(zhí)行操作(設(shè)置單列的時(shí)候經(jīng)常用到)
//GCD提供了一個(gè)一次執(zhí)行的機(jī)制,不僅能夠保證只會被執(zhí)行一次.而且是線程安全的!
//GCD-Once 內(nèi)部是會加鎖!! 但是 比普通的互斥鎖 效率高 100多倍 蘋果推薦使用這個(gè)
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
});
3 調(diào)度組?
//MARK: 調(diào)度組
-(void)group1{
//1.隊(duì)列
dispatch_queue_t q = dispatch_get_global_queue(0, 0);
//2.調(diào)度組
dispatch_group_t g = dispatch_group_create();
//3.添加任務(wù),讓隊(duì)列執(zhí)行,任務(wù)執(zhí)行情況最終通知組
dispatch_group_async(g, q, ^{
NSLog(@"download A %@",[NSThread currentThread]);
});
dispatch_group_async(g, q, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"download B %@",[NSThread currentThread]);
});
dispatch_group_async(g, q, ^{
[NSThread sleepForTimeInterval:0.8];
NSLog(@"download C %@",[NSThread currentThread]);
});
//4. 所有任務(wù)執(zhí)行完畢后,獲得通知
//用一個(gè)調(diào)度組,可以監(jiān)聽全局隊(duì)列調(diào)度的任務(wù),執(zhí)行完畢之后,在主隊(duì)列執(zhí)行最終處理!
//dispatch_group_notify 本身是異步的
dispatch_group_notify(g, dispatch_get_main_queue(), ^{
//更新UI,通知用戶
NSLog(@"OK? %@",[NSThread currentThread]);
});
NSLog(@"come here");
}
//MARK: 主隊(duì)列,同步任務(wù)
//阻塞主線程!!
-(void)gcdDemo2{
//1.隊(duì)列? -> 一啟動就有主線程,主隊(duì)列只需要獲取
dispatch_queue_t q = dispatch_get_main_queue();
NSLog(@"這里!!");
//2.同步任務(wù)
dispatch_sync(q, ^{
NSLog(@"能來嗎?");
});
NSLog(@"come here -- %@",[NSThread currentThread]);
}
5 GCD總結(jié)
/**
GCD 核心概念:將任務(wù)添加到隊(duì)列,指定任務(wù)執(zhí)行的方法
- 任務(wù)
- 使用block 封裝
- block就是一個(gè)提前準(zhǔn)備好的代碼塊,在需要的時(shí)候執(zhí)行
- 隊(duì)列(負(fù)責(zé)調(diào)度任務(wù))
- 串行隊(duì)列:一個(gè)接一個(gè)的調(diào)度任務(wù)
- 并發(fā)對象:可以同時(shí)調(diào)度多個(gè)任務(wù)
- 執(zhí)行任務(wù)的函數(shù)
- 同步執(zhí)行: 當(dāng)前指令不完成,就不會執(zhí)行下一條指令
- 異步執(zhí)行: 當(dāng)前執(zhí)行不完成,同樣可以執(zhí)行下一條指令
小結(jié):
- 開不開線程,取決于同步\異步. 同步,不開!? 異步,開!
- 開多少條線程,取決于隊(duì)列,串行開一條,并發(fā)(異步)開多條!
hank:開啟子線程只能是異步!!!? 線程多開\并發(fā)且異步
只要是異步就開啟子線程!!!
全局隊(duì)列 & 并發(fā)隊(duì)列
1. 名稱,并發(fā)隊(duì)列有名稱,適合大型項(xiàng)目跟蹤錯誤報(bào)告!
2. release,在 MRC 開發(fā)時(shí),并發(fā)隊(duì)列需要使用 dispatch_release(q);
結(jié)論:目前絕大多數(shù)軟件都會使用全局隊(duì)列.
全局隊(duì)列 & 串行隊(duì)列
全局隊(duì)列(并發(fā)): 并發(fā),能夠調(diào)度多個(gè)線程,執(zhí)行效率高!!!
- 費(fèi)電!!
串行隊(duì)列: 一個(gè)接一個(gè),只能開啟一條線程,執(zhí)行效率低!!
- 省電,省錢,省流量
選擇的依據(jù): 根據(jù)用戶的上網(wǎng)方式!!
- WIFI ,可以開多條線程, 6條
- 3G\4G,盡量少開線程,2~3 條
四 ?NSOperation
特點(diǎn): ? 不能直接使用
目的: ?定義子類中共有的屬性和方法
子類:- NSInvocationOperation ? ?- NSBlockOperation
1. ? 創(chuàng)建 ? //? ? NSInvocationOperation 操作
NSInvocationOperation * op = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downloadImage:) object:@"Hank"];
//start 方法,會在當(dāng)前線程執(zhí)行調(diào)度方法
//? ? [op start];
//1.隊(duì)列
NSOperationQueue * q = [[NSOperationQueue alloc]init];
//2.將操作添加到隊(duì)列 - 會自動異步執(zhí)行調(diào)度方法
[q addOperation:op];
2. ? ?//NSBlockOperation 所有的代碼都寫在一起.更加好維護(hù)
NSOperationQueue * q = [[NSOperationQueue alloc]init];
NSBlockOperation * op = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@ ---- %d",[NSThread currentThread],i);
}];
[q addOperation:op];
二 ?線程間的通訊
[self.opQueue addOperationWithBlock:^{
NSLog(@"耗時(shí)操作!! %@",[NSThread currentThread]);
//主線程 更新UI ,主隊(duì)列
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"UIUIUI --- %@",[NSThread currentThread]);
}];
}];
三 ?依賴關(guān)系
/**
需求:從網(wǎng)上下載視頻\完成之后解碼\通知用戶
*/
//1.下載
NSBlockOperation * op1 = [NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:3.0];
NSLog(@"下載? -? %@",[NSThread currentThread]);
}];
//2.解碼
NSBlockOperation * op2 = [NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:2.0];
NSLog(@"解碼? -? %@",[NSThread currentThread]);
}];
//3.通知用戶
NSBlockOperation * op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"通知用戶? -? %@",[NSThread currentThread]);
}];
//NSOperation 提供了依賴關(guān)系
//NSOperation 的所有的操作都是異步執(zhí)行的,但是為了建立任務(wù)之間的依賴,提供了dependency的功能
//GCD中,通過同步任務(wù)來實(shí)現(xiàn),也可以通過串行隊(duì)列!
[op2 addDependency:op1];//op2 依賴于 op1? == op1 執(zhí)行完畢 op2 開始執(zhí)行
[op3 addDependency:op2];
// !!千萬注意!!!:? 不要循環(huán)依賴!!!!,一旦指定了循環(huán)依賴,隊(duì)列就不能執(zhí)行被循環(huán)依賴的操作了!!
//不會造成死鎖!? 但是 以前的版本 會死鎖!!
//? ? [op1 addDependency:op3];
[self.opQueue addOperations:@[op1,op2] waitUntilFinished:NO];
//主線程通知用戶
[[NSOperationQueue mainQueue] addOperation:op3];
NSLog(@"come here");
四 ?取消線程
//提示: 取消操作,同樣不會取消正在執(zhí)行中的操作
[self.opQueue cancelAllOperations];
五 暫停/恢復(fù)線程
//在設(shè)置隊(duì)列的暫停屬性時(shí),并不會判斷隊(duì)列中是否有操作!
//如果不希望用戶產(chǎn)生困惑,可以提前做判斷
//判斷隊(duì)列中當(dāng)前是否有操作
if (self.opQueue.operationCount == 0){
NSLog(@"沒有操作!!!");
return ;
}
if (self.opQueue.isSuspended) {
//在暫停的時(shí)候,隊(duì)列中的操作數(shù),是包含正在執(zhí)行的操作!!
NSLog(@"繼續(xù) %tu",self.opQueue.operationCount);
self.opQueue.suspended = NO;
}else{
//再次繼續(xù)運(yùn)行的時(shí)候,如果之前執(zhí)行的操作已經(jīng)完成,隊(duì)列中的操作數(shù)就只有未調(diào)度的了!!
NSLog(@"暫停 %tu",self.opQueue.operationCount);
self.opQueue.suspended = YES;
}
六 最大線程
//設(shè)置同時(shí)最大并發(fā)操作數(shù)量
//WIFI: 5~6
//2G/3G/4G: 2~3
self.opQueue.maxConcurrentOperationCount = 2;
//向隊(duì)列添加任務(wù)
//從 iOS 8.0 開始,無論使用GCD 還是 NSOperation, 都會開啟很多線程
//在 iOS 7.0 以前,GCD 通常只會開啟 5 ~ 6 條線程!
//目前線程數(shù)量多說明:
//1.底層的線程池更大了,能夠拿到的線程資源更多了!
//2.對控制同時(shí)并發(fā)的線程數(shù),要求就更高!
GCD和NSOpration的比較
/*
NSOperation 是蘋果公司大力推薦的"并發(fā)"技術(shù)! 開發(fā)者已經(jīng)不需要關(guān)心線程以及線程的生命周期!
,而且我們逃離了GCD的 并發(fā)還是串行 異步還是同步!
NSOperation 的核心概念: 將"操作" 添加到 "隊(duì)列"
GCD的核心概念: 將"任務(wù)"添加到隊(duì)列,指定任務(wù)的執(zhí)行函數(shù)(方法)
----------------------------------------------------------------------------------
GCD & NSOperation 的對比
GCD 在 iOS 4.0推出的,主要針對多核處理器做了優(yōu)化的并發(fā)技術(shù),是 C 語言!
- 將"任務(wù)"[block]"添加到"隊(duì)列[串行/并發(fā)/主隊(duì)列/全局],并且指定執(zhí)行任務(wù)的函數(shù)[同步/異步]
- 線程間的通訊 dispatch_get_main_queue()
- 提供了一些 NSOperation 不具備的功能
- 一次執(zhí)行(單例設(shè)計(jì)模式最常用)
- 延遲執(zhí)行
- 調(diào)度組
- 等等...
NSOperation 在 iOS 2.0 推出的!
- 將操作[異步執(zhí)行的任務(wù)] 添加到 隊(duì)列[并發(fā)隊(duì)列],就會立刻異步執(zhí)行
- mainQueue
- 提供了一些 GCD 實(shí)現(xiàn)起來比較困難的功能
- 最大并發(fā)線程數(shù)
- 隊(duì)列的暫停/繼續(xù)
- 取消所有操作
- 指定操作之間的依賴關(guān)系(GCD 同步實(shí)現(xiàn))
----------------------------------------------------------------------------------
NSOperation類是一個(gè)抽象類
特點(diǎn):
- 不能直接使用
目的:
- 定義子類中共有的屬性和方法
子類:
- NSInvocationOperation
- NSBlockOperation
*/