******************************************************************************************
pthread
******************************************************************************************
pthread 使用方法
pthread是C語言的多線程庫,使用pthread需要首先添加頭文件<pthread.h>
1. 聲明和實現(xiàn)一個函數(shù)
void *task(void *param){
// 執(zhí)行任務(wù)的代碼
return NULL;
}
2. 在合適的位置開啟多線程執(zhí)行之前聲明的函數(shù)
// 聲明一個線程
pthread_t thread;
// 調(diào)用線程函數(shù)
pthread_create(&thread, NULL, task, NULL);
3. 判斷兩個線程是否相同的函數(shù)
pthread_equal(threadA, threadB);
******************************************************************************************
NSThread
******************************************************************************************
NSThread 使用方法
NSThread 是OC的方法,封裝了pthread沮脖,使操作更加面向?qū)ο蟆?/p>
NSThread的方法
// 創(chuàng)建線程的方法
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@(task) object:nil];
// 設(shè)置線程名稱
thread.name = @"線程方法";
// 設(shè)置線程優(yōu)先級
thread.threadPriority = 0.0-1.0; // 默認0.5
// 啟動線程
[thread start];
**************************************************************
// 使用分離的方法獲得線程
[NSThread detachNewThreadSelector:@selector(task) toTarget:self withObject:nil];
**************************************************************
// 開啟一條后臺的線程
[self performSelectInBackground:@selector(task) withObject:nil];
**************************************************************
// 獲得主線程
NSThread *mainThread = [NSThread mainThread];
**************************************************************
// 獲得當前線程
NSThread *currentThread = [NSThread currentThread];
**************************************************************
線程的操作方法
// start方法 new -> runabled
[thread start];
// 線程進入阻塞狀態(tài) run -> blocked
[NSThread sleepUntilDate:date];
[NSThread sleepForTimeInterval:timeInterval];
// 強制停止線程
[NSThread exit];
使用線程鎖
@synchronized(self){
// 為了防止死鎖,使用線程鎖可以讓線程訪問一塊資源的時候為它加上鎖。
// 一般使用self饲鄙,必須是全局唯一的對象凄诞。
// 加鎖的代碼
}
線程之間的通信
// 線程通信是直接調(diào)用主線程的方法
[self performSelectorOnMainThread:@selector(task) withObject:nil waitUntilDone:YES/NO];
// 最后一個參數(shù)指是否等待task完成再執(zhí)行后面的代碼。
// 判斷當前線程是否為主線程
BOOL isMainThread = [[NSThread currentThread] isMainThread];
******************************************************************************************
GCD
******************************************************************************************
GCD: Grand Central Dispatch
GCD 能夠充分利用CPU多核進行并行運算
創(chuàng)建隊列
1. 創(chuàng)建并發(fā)隊列 Concurrent Dispatch Queue
dispatch_queue_t queue = dispatch_queue_create("com.baidu.download", DISPATCH_QUEUE_CONCURRENT);
2. 獲得全局并發(fā)隊列
dispatch_queue_t queue = dispatch_get_global_queue(0,0);
{ // 第一個參數(shù)是優(yōu)先級
DISPATCH_QUEUE_PRIORITY_HIGH
DISPATCH_QUEUE_PRIORITY_DEFAULT
DISPATCH_QUEUE_PRIORITY_LOW
DISPATCH_QUEUE_PRIORITY_BACKGROUND
}
3. 創(chuàng)建串行隊列 Serial Dispatch Queue
dispatch_queue_t queue = dispatch_queue_create("com.baidu.download", DISPATCH_QUEUE_SERIAL)
4. 獲得主隊列 UI線程 (全局串行隊列)
dispatch_queue_t queue = dispatch_get_main_queue();
創(chuàng)建函數(shù)
1. 同步函數(shù) // queue不能使用主隊列忍级,不然會產(chǎn)生死鎖帆谍。
dispatch_sync(queue, block);
2. 異步函數(shù)
dispatch_async(queue, block);
GCD常用函數(shù)
1. 延遲執(zhí)行代碼的方法 // 第一個參數(shù)指從現(xiàn)在開始, 第二個參數(shù)指兩秒后開始
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), queue, ^{...});
2. 一次性代碼: 單例demo
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{...});
3. 柵欄函數(shù) // queue不能使用全局并發(fā)隊列
dispatch_barrier_async(queue, ^{...});
4. 快速迭代代碼 // 第一個參數(shù)是迭代次數(shù) ,
// 第二個參數(shù)使用并發(fā)隊列轴咱,如果使用串行隊列就沒有意義了.
dispatch_apply(n, queue, ^(size_t i){...});
隊列組函數(shù)
// 創(chuàng)建隊列組
dispatch_group_t group = dispatch_group_create();
// 執(zhí)行隊列組函數(shù)
dispatch_group_async(group, queue, ^{...});
// 監(jiān)聽隊列組函數(shù)是否執(zhí)行完畢,組內(nèi)線程執(zhí)行完畢后執(zhí)行自己的函數(shù)
// 這個函數(shù)是異步執(zhí)行的汛蝙,不會阻塞后續(xù)代碼執(zhí)行
dispatch_group_notify(group, queue, ^{...});
// wait函數(shù)會阻塞線程,直到隊列組任務(wù)結(jié)束
dispatch_group_Wait(group, DISPATCH_TIME_FOREVER);
******************************************************************************************
NSOperation
******************************************************************************************
NSOperation
NSOperation 是個抽象類朴肺,與NSOperationQueue搭配使用時可以開啟多線程窖剑。它有兩個子類,NSInvocationOperation 和 NSBlockOperation戈稿。
使用方法: 封裝操作 --> 添加到隊列西土。
封裝操作的方法
// 使用NSInvocationOperation封裝操作并啟動。這時候不會開線程
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task) object:nil];
[operation start];
****************************************************************
// 使用NSBlockOperation封裝操作鞍盗。封裝的操作不會開啟線程
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{...}];
// NSBlockOperation有一個追加操作的方法需了,追加的操作會自動開啟線程執(zhí)行。
[operation addExecutionBlock:^{...}];
[operation start];
****************************************************************
// 自定義[操作]
// 自定義一個繼承自NSOperation的類般甲,重寫main方法肋乍,將操作放到main方法中,使用init方法創(chuàng)建出來后可以直接添加到隊列中執(zhí)行操作敷存。
//*****main方法中存放需要封裝的耗時操作*****
添加到隊列
// NSOperation里有兩種隊列墓造,主隊列和非主隊列。
// 主隊列獲得方法
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
****************************************************************
// 非主隊列只能創(chuàng)建,init出來的隊列默認為非主隊列锚烦。
NSOperationQueue *queue = [[NSOperationQueue alloc]
init];
// 操作非主隊列的maxConcurrentOperationCount屬性可以實現(xiàn)并發(fā)和串行的模式
// ****當i=1的時候滔岳,隊列也會開多條線程,但是多個操作在不同線程中會串行執(zhí)行****
// 當i=0時表示最大并發(fā)數(shù)為0挽牢,不會開啟線程則不會執(zhí)行操作
// i=-1谱煤,默認值,表示最大值禽拔。
queue.maxConcurrentOperationCount = (NSInteger)i;
// 將任務(wù)添加到隊列刘离,隊列會自動調(diào)用任務(wù)的start方法并且開啟線程
[queue addOperation:operation];
****************************************************************
// 隊列可以使用快捷添加操作的方法
[queue addOperationWithBlock:^{}];
控制隊列內(nèi)操作的方法
// 操作的暫停和繼續(xù)
// ***已經(jīng)開始的線程是無法暫停的***
queue.suspended = YES; // 暫停操作
queue.suspended = NO; // 開始操作
****************************************************************
// 取消操作
// ***已經(jīng)開始的操作是無法取消的,取消后無法再次啟動***
// 因為耗時操作執(zhí)行時間太長睹栖,導致取消操作后已經(jīng)啟動的線程還在繼續(xù)執(zhí)行硫惕,可以使用在多個
// 位置添加代碼判斷是否取消了操作溺忧,提升用戶體驗.
// cancelAllOperations方法是調(diào)用所有操作的cancel方法,所以使用以下代碼
// *** if(self.isCancelled) return; ***[添加到耗時操作內(nèi)部隨時判斷]
[queue cancelAllOperations];
****************************************************************
// 控制操作的執(zhí)行順序
// 使用依賴的方法控制每個操作的執(zhí)行順序避诽,注意不能產(chǎn)生循環(huán)以來。
// ***即使操作在不同的隊列植捎,也可以跨隊列添加依賴關(guān)系***
[operationA addDependency:operationB];
// 執(zhí)行完B之后才會執(zhí)行A
// 使用監(jiān)聽的方法控制操作的執(zhí)行順序
// A執(zhí)行完畢后才會進入block執(zhí)行,block的代碼系統(tǒng)會自動開啟多線程執(zhí)行豁辉。
operationA.completionBlock = ^{...};【異步執(zhí)行】
線程之間的通信
// NSOperation的線程間通信可以直接使用隊列調(diào)用方法
// 在非主隊列中調(diào)用主隊列操作可以直接在非主隊列操作中調(diào)用方法:
[[NSOperationQueue mainQueue] addOperationWithBlock:^{...}];