進程
1.正在進行的一個過程或任務(wù),負責任務(wù)執(zhí)行的是cpu尚困。
2.每個進程之間是獨立的椎例,每個進程都運行在獨立的內(nèi)存空間內(nèi),并擁有獨立運行所需的全部資源印颤。
線程
1.程序運行時的最小單位您机,是進程的實際運作單位。
2.進程想要執(zhí)行任務(wù)必須至少有一個線程年局。在應(yīng)用程序啟動時际看,系統(tǒng)會默認開啟一個線程,即主線程矢否。
進程和線程的關(guān)系
1.線程在進程下進行
2.一個進程可以包含多個線程
3.同一個進程內(nèi)不同的線程間數(shù)據(jù)容易共享
4.進程是用內(nèi)存地址可以上鎖仲闽,即一個線程使用共享內(nèi)存時,其他線程必須等待其結(jié)束僵朗,才能使用赖欣。(互斥鎖)
5.進程使用的內(nèi)存地址也可以限定使用,即當前只允許2 人訪問验庙,第三人需要等待有人結(jié)束訪問后再進行訪問顶吮。(信號量)
6.一個程序有多個進程,一個進程可以有多個線程粪薛,但每個進程至少要有一個線程悴了。
多線程
1.多條線程并發(fā)執(zhí)行,cpu快速的在多條線程之間調(diào)度违寿。 如果cpu調(diào)度線程時間足夠的快湃交,就造成了多線程并發(fā)的假象。
2.如果線程非常多陨界,也會大量消耗cpu資源巡揍。
3.多線程可以提高程序的執(zhí)行效率,能適當提高資源的利用率菌瘪。
4.如果開啟大量的線程會占用內(nèi)存空間腮敌,降低程序性能阱当。
隊列
串行隊列
同一時間內(nèi),隊列中只能執(zhí)行一個任務(wù)糜工,當前任務(wù)結(jié)束后才能執(zhí)行下一個任務(wù)弊添。
并發(fā)隊列
同時允許多個任務(wù)并發(fā)執(zhí)行。
iOS中的多線程
GCD
1.獲取主線程
dispatch_queue_t main_queue = dispatch_get_main();
2.線程延時
/**
DISPATCH_TIME_NOW : 現(xiàn)在
DISPATCH_TIME_FOREVER : 永遠超時
NSEC_PER_SEC : 秒 (1000,000,000 納秒 = 1秒) 可精確到納秒級捌木,eg. 0.1 * NSEC_PER_SEC 是0.1 * 1000,000,000 = 100,000,000 納秒 = 0.1秒 以下算法雷同油坝。
NSEC_PER_MSEC : 毫秒 (1000,000 納秒 = 1 毫秒)可精確到毫秒級
USEC_PER_SEC : 秒 (1000000微秒 = 1秒) 可精確到微秒級
NSEC_PER_USEC : 微秒 (1000納秒 = 1 微秒) 可精確到納秒級
*/
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), main_queue, ^{
NSLog(@"哈哈");
})
3.只執(zhí)行一次,常用作單例模式
static dispatch_once_t once;
dispatch_once(&once, ^{
// 只實例化一次
personModel = [[self alloc] init];
});
4.線程組刨裆,即等待一組任務(wù)完成后繼續(xù)執(zhí)行下一步澈圈,常被應(yīng)用在圖片上傳
// 開啟全集并發(fā)線程,DISPATCH_QUEUE_PRIORITY_DEFAULT 是線程等級帆啃, 0 是flag瞬女,備用字段,通常設(shè)置0
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
// 進行操作1
});
dispatch_group_async(group, queue, ^{
// 進行操作2
});
dispatch_group_async(group, queue, ^{
// 進行操作3
});
dispatch_group_notify(group, queue, ^{
// 操作1努潘。2诽偷。3 執(zhí)行完畢 進行 下一步操作
});
// 超時等待,即設(shè)置一個最長等待時常疯坤,超過時間后 調(diào)起 notify block
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
5.信號量报慕,設(shè)置最大并發(fā)線程數(shù),設(shè)置數(shù)大于1時順序不能保證
//創(chuàng)建信號量压怠, 2為設(shè)置最大并發(fā)線程
dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
for (int i = 0; i < 5; i++) {
// 創(chuàng)建異步線程
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 信號量的等待時長眠冈,這里設(shè)置為一直等待,當信號量小于0 時一直等待刑峡,如果大于1則進入且降低信號量即-1
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
// 睡眠2秒
sleep(2);
// po 出當前線程洋闽, 顯示log
NSLog(@"%@", [NSThread currentThread]);
// 標記信號量 + 1
dispatch_semaphore_signal(semaphore);
});
}
for (int i = 0; i < 5; i++) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
sleep(2);
NSLog(@"%@", [NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
});
}
NSOPeration
NSOperation是基于GCD的抽象基類。
NSOperation可以跨隊列設(shè)置依賴關(guān)系
NSOperation面向?qū)ο笸幻危С諯VO诫舅,可以檢測operation是否正在執(zhí)行,是否結(jié)束或者取消
NSOperation實體子類有兩個宫患,NSBlockOperation 和 NSInvocationOperation
// 初始化 方法實例
NSInvocationOperation *invoOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(haha:) object:nil];
[invoOperation start];
// 初始化 block塊 實例
NSBlockOperation *blockOpertaion = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"ni hao ");
}];
// 繼續(xù)添加線程
blockOperation add
[blockOpertaion start];
// 以下為 依賴關(guān)系
// 獲取 主線程
NSOperationQueue *main_Operation = [NSOperationQueue mainQueue];
// 創(chuàng)建 各種線程
NSOperation *person_a = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"我是 神秘人 A");
}];
NSOperation *person_b = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"我是 神秘人 B");
}];
NSOperation *person_c = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"我是 神秘人 C");
}];
// 添加依賴關(guān)系挑围, A以來 B和C 松申,相當于 A要在 B C 之后才能執(zhí)行任務(wù)
[person_a addDependency:person_b];
[person_a addDependency:person_c];
//添加到 主線程中 查看順序
[main_Operation addOperation:person_a];
[main_Operation addOperation:person_b];
[main_Operation addOperation:person_c];
NSThread
NSThread使用比較簡單垄懂,可以靜態(tài)獲取線程信息
// 獲取主線程
NSThread *thread = [NSThread mainThread];
// 判斷是否開啟了多線程
BOOL isOpenThread = [NSThread isMultiThreaded];
// 獲取當前線程
NSThread *currentThread = [NSThread currentThread];
// 當前線程睡眠 時間(s) 10秒鐘
[NSThread sleepForTimeInterval:10];
// 睡眠到指定時間 , 以下為當前時間往后延10秒鐘
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]];
// 退出當前線程 围来, 禁止在主線程使用
//[NSThread exit];
// 初始化線程對象 實例化對象
/*
qualityOfService 線程的優(yōu)先級
NSQualityOfServiceUserInteractive 最高級別,用于UI交互皇帮,點擊事件卷哩,繪制圖形等
NSQualityOfServiceUserInitiated = 次高級別,用于執(zhí)行立即返回的任務(wù)
NSQualityOfServiceUtility 普通級別属拾,不需要立即返回的任務(wù)
NSQualityOfServiceBackground 后臺級別将谊,完全不緊急的任務(wù)
NSQualityOfServiceDefault 默認級別
*/
NSLog(@"%@", [NSThread currentThread]);
NSThread *asynThread = [[NSThread alloc] initWithTarget:self selector:@selector(hello) object:nil];
// 設(shè)置 線程實例化對象的 優(yōu)先級別冷溶,默認為 默認級別
asynThread.qualityOfService = NSQualityOfServiceDefault;
// 開始線程
[asynThread start];
// 也可以快速創(chuàng)建線程
[NSThread detachNewThreadSelector:@selector(hello) toTarget:self withObject:nil];
__weak typeof(self) weakSelf = self;
[NSThread detachNewThreadWithBlock:^{
// po 出當前線程
NSLog(@"%@", [NSThread currentThread]);
// 回到主線程
[weakSelf performSelectorOnMainThread:@selector(hello) withObject:nil waitUntilDone:NO];
}];
// 還有一些 創(chuàng)建線程的方法
// 3 秒后執(zhí)行 hello 方法 , 在當前線程
[self performSelector:@selector(hello) withObject:nil afterDelay:3];
// 后臺異步執(zhí)行
[self performSelectorInBackground:@selector(hello) withObject:nil];
// 在主線程上執(zhí)行 hello 方法
[self performSelectorOnMainThread:@selector(hello) withObject:nil waitUntilDone:NO];
// 在 指定的 asynThread 線程上執(zhí)行 hello方法 *** 注意避免在子線程中執(zhí)行 ui交互
[self performSelector:@selector(hello) onThread:asynThread withObject:nil waitUntilDone:NO];