關于進程和線程:
進程:進程是指在系統(tǒng)中正在運行的一個應用程序
每個進程之間是獨立的.
線程:一個進程要想執(zhí)行任務,必須得有線程(每一個進程中至少要有一個線程),進程只幫你分配內(nèi)存.
線程是進程的基本執(zhí)行單元
注:多線程同時執(zhí)行,其實是CPU快速地在多線程之間調(diào)度,同一時間,CPU只能處理一條線程.
主線程:一個iOS程序運行后,默認會開啟一條線程,即”主線程”.或”UI線程”
主線程作用:顯示/刷新UI界面 處理UI事件
主線程使用注意:別將比較耗時的操作放到主線程中(下載)
線程同步:
1.實質(zhì):為了防止多個線程搶奪同一個資源造成的數(shù)據(jù)安全問題
2.實現(xiàn):給代碼加一個互斥鎖(同步鎖)
@synchronized(self){
// 被鎖住的代碼
}
關于GCD:
什么是GCD : 牛逼的中樞調(diào)度器,純C.
優(yōu)勢:GCD是蘋果公司為多核的并行運算提出的解決方案
GCD會自動利用更多的CPU內(nèi)核(雙核,四核)
GCD會自動管理線程的生命周期 (創(chuàng)建線程,調(diào)度任務,銷毀線程)
程序員只需告訴GCD想要執(zhí)行什任務,不需要編寫任何線程管理代碼
任務和隊列
任務:執(zhí)行什么操作
隊列:用來存放任務
使用就2步驟:
定制任務;
將任務添加到隊列中(任務取出遵循FIFO,先進先出 后進后出)
同步與異步
同步: 只能在當前線程中執(zhí)行任務,不具備開啟新線程的能力
異步:可以在新的線程中執(zhí)行任務,具備開啟新線程的能力
我們很多時候會混淆一些術語: 同步 異步 串行 并發(fā)
同步和異步主要影響:能不能開啟新的線程
并發(fā)和串行主要影響:任務的執(zhí)行方式
并發(fā):多個任務并發(fā)(同時)執(zhí)行
串行:一個任務執(zhí)行完畢后,再執(zhí)行下一個任務
// dispatch_sync : 同步猜丹,不具備開啟線程的能力
// dispatch_async : 異步模闲,具備開啟線程的能力
// 并發(fā)隊列 :多個任務可以同時執(zhí)行
// 串行隊列 :一個任務執(zhí)行完后,再執(zhí)行下一個任務
隊列:存放任務
全局并發(fā)隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
自己創(chuàng)建的串行隊列
dispatch_queue_t queue = dispatch_queue_create("cn.yj.queue", NULL);
主隊列
dispatch_queue_t queue = dispatch_get_main_queue();
線程間的通信:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 執(zhí)行耗時的異步操作
dispatch_async(dispatch_get_main_queue(), ^{
//回到主線程,執(zhí)行UI刷新操作
});
});
- 延時執(zhí)行
// 3秒后回到主線程執(zhí)行block中的代碼
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
NSLog(@"------task------%@", [NSThread currentThread]);
});
// 3秒后自動開啟新線程 執(zhí)行block中的代碼
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
NSLog(@"------task------%@", [NSThread currentThread]);
});
- 一次性執(zhí)行
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"----once");
});
- 組隊列
如果我們想同時下載兩張圖片,再合并,可以利用組隊列
// 1.隊列組
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 2.下載圖片1
__block UIImage *image1 = nil;
dispatch_group_async(group, queue, ^{
NSURL *url1 = [NSURL URLWithString:@"http://g.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee460de6182ff5e0fe99257e80.jpg"];
NSData *data1 = [NSData dataWithContentsOfURL:url1];
image1 = [UIImage imageWithData:data1];
});
// 3.下載圖片2
__block UIImage *image2 = nil;
dispatch_group_async(group, queue, ^{
NSURL *url2 = [NSURL URLWithString:@"http://su.bdimg.com/static/superplus/img/logo_white_ee663702.png"];
NSData *data2 = [NSData dataWithContentsOfURL:url2];
image2 = [UIImage imageWithData:data2];
});
// 4.合并圖片 (保證執(zhí)行完組里面的所有任務之后鞭光,再執(zhí)行notify函數(shù)里面的block)
dispatch_group_notify(group, queue, ^{
// 開啟一個位圖上下文
UIGraphicsBeginImageContextWithOptions(image1.size, NO, 0.0);
// 繪制第1張圖片
CGFloat image1W = image1.size.width;
CGFloat image1H = image1.size.height;
[image1 drawInRect:CGRectMake(0, 0, image1W, image1H)];
// 繪制第2張圖片
CGFloat image2W = image2.size.width * 0.5;
CGFloat image2H = image2.size.height * 0.5;
CGFloat image2Y = image1H - image2H;
[image2 drawInRect:CGRectMake(0, image2Y, image2W, image2H)];
// 得到上下文中的圖片
UIImage *fullImage = UIGraphicsGetImageFromCurrentImageContext();
// 結(jié)束上下文
UIGraphicsEndImageContext();
// 5.回到主線程顯示圖片
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = fullImage;
});
});