
屏幕快照 2017-06-18 下午11.46.26.png
Pthread
//1.創(chuàng)建線程對象
pthread_t thread;
//2.創(chuàng)建線程
/*
第一個參數(shù):線程對象 傳遞地址
第二個參數(shù):線程的屬性 NULL
第三個參數(shù):指向函數(shù)的指針
第四個參數(shù):函數(shù)需要接受的參數(shù)
*/
pthread_create(&thread, NULL, task, NULL);
void *task(void *param)
{
for (NSInteger i = 0; i<10000; i++) {
NSLog(@"%zd----%@",i,[NSThread currentThread]);
}
// NSLog(@"%@--------",[NSThread currentThread]);
return NULL;
}
NSThread
//1.創(chuàng)建線程
/*
第一個參數(shù):目標對象 self
第二個參數(shù):方法選擇器 調用的方法
第三個參數(shù):前面調用方法需要傳遞的參數(shù) nil
*/
XMGThread *threadA = [[XMGThread alloc]initWithTarget:self selector:@selector(run:) object:@"ABC"];
//設置屬性
threadA.name = @"線程A";
//設置優(yōu)先級 取值范圍 0.0 ~ 1.0 之間 最高是1.0 默認優(yōu)先級是0.5
threadA.threadPriority = 1.0;
//2.啟動線程
[threadA start];
[NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"分離子線程"];
3.開啟后臺線程
[self performSelectorInBackground:@selector(run:) withObject:@"開啟后臺線程"];
線程安全
while (1) {
//鎖:必須是全局唯一的
//1.注意枷鎖的位置
//2.注意枷鎖的前提條件,多線程共享同一塊資源
//3.注意加鎖是需要代價的,需要耗費性能的
//4.加鎖的結果:線程同步
@synchronized(self) {
//線程1
//線程2
//線程3
NSInteger count = self.totalCount;
if (count >0) {
for (NSInteger i = 0; i<1000000; i++) {
}
self.totalCount = count - 1;
//賣出去一張票
NSLog(@"%@賣出去了一張票,還剩下%zd張票", [NSThread currentThread].name,self.totalCount);
}else
{
NSLog(@"不要回公司上班了");
break;
}
}
}
GCD

屏幕快照 2017-06-19 上午12.11.12.png
1.異步函數(shù)+并發(fā)隊列:會開啟多條線程,隊列中的任務是并發(fā)執(zhí)行
//獲得全局并發(fā)隊列
/*
第一個參數(shù):優(yōu)先級
第二個參數(shù):
*/
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSLog(@"---satrt----");
//2.1>封裝任務2>添加任務到隊列中
/*
第一個參數(shù):隊列
第二個參數(shù):要執(zhí)行的任務
*/
dispatch_async(queue, ^{
NSLog(@"download1----%@",[NSThread currentThread]);
});
2.異步函數(shù)+串行隊列:會開線程,開一條線程,隊列中的任務是串行執(zhí)行的
//1.創(chuàng)建隊列
dispatch_queue_t queue = dispatch_queue_create("download", DISPATCH_QUEUE_SERIAL);
//2.封裝操作
dispatch_async(queue, ^{
NSLog(@"download1----%@",[NSThread currentThread]);
});
3.同步函數(shù)+并發(fā)隊列:不會開線程,任務是串行執(zhí)行的
//1.創(chuàng)建隊列
dispatch_queue_t queue = dispatch_queue_create("com.520it.download", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"---start---");
//2.封裝任務
dispatch_sync(queue, ^{
NSLog(@"download1----%@",[NSThread currentThread]);
});
4.同步函數(shù)+串行隊列:不會開線程,任務是串行執(zhí)行的
//1.創(chuàng)建隊列
dispatch_queue_t queue = dispatch_queue_create("com.520it.download", DISPATCH_QUEUE_SERIAL);
//2.封裝任務
dispatch_sync(queue, ^{
NSLog(@"download1----%@",[NSThread currentThread]);
});
5.異步函數(shù)+主隊列:所有任務都在主線程中執(zhí)行,不會開線程
//1.獲得主隊列
dispatch_queue_t queue = dispatch_get_main_queue();
//2.異步函數(shù)
dispatch_async(queue, ^{
NSLog(@"download1----%@",[NSThread currentThread]);
});
//同步函數(shù)+主隊列:死鎖
//注意:如果該方法在子線程中執(zhí)行,那么所有的任務在主線程中執(zhí)行,
-(void)syncMain
{
//1.獲得主隊列
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"start----");
//2.同步函數(shù)
//同步函數(shù):立刻馬上執(zhí)行,如果我沒有執(zhí)行完畢,那么后面的也別想執(zhí)行
//異步函數(shù):如果我沒有執(zhí)行完畢,那么后面的也可以執(zhí)行
dispatch_sync(queue, ^{
NSLog(@"download1----%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"download2----%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"download3----%@",[NSThread currentThread]);
});
NSLog(@"end---");
}
死鎖解釋
先請看下面這張圖,相信大家都知道會死鎖,為什么呢。
往串行隊列添加的任務需要等到串行隊列前面的任務都執(zhí)行完畢才會開始執(zhí)行。拋開你所謂的堵塞概念,我不認為這是適合的描述。對于在主線程,你可以認為每一語句都是將任務插入主隊列。調用dispatch_sync這個函數(shù)相當于將一個任務插入主隊列,這個函數(shù)的作用是將一個任務插入指定隊列,當這個函數(shù)里的Block執(zhí)行完畢以后,這個函數(shù)才會返回,即這個調用這個dispatch_sync的任務結束,主隊列繼續(xù)往下添加任務。我上面說了,串行的任務添加后需要等前面的任務都執(zhí)行完才會執(zhí)行的。所以Block里的任務需要等dispatch_sync這個調用執(zhí)行完才會執(zhí)行,然而dispatch_sync并不會返回。
第二個是創(chuàng)建了一個空的串行隊列,dispatch_sync這個是主隊列添加的任務,工作是將一個任務添加到這個新創(chuàng)建的隊列上,由于指定的隊列前面沒有其他任務,所以這個任務先執(zhí)行,然后返回,dispatch_sync返回,主隊列繼續(xù)往下添加任務。

線程通訊
//1.創(chuàng)建子線程下載圖片
//DISPATCH_QUEUE_PRIORITY_DEFAULT 0
dispatch_async(dispatch_get_global_queue(0, 0), ^{
//1.1 確定url
NSURL *url = [NSURL URLWithString:@"http://a.hiphotos.baidu.com/zhidao/wh%3D450%2C600/sign=da0ec79c738da9774e7a8e2f8561d42f/c83d70cf3bc79f3d6842e09fbaa1cd11738b29f9.jpg"];
//1.2 下載二進制數(shù)據(jù)到本地
NSData *imageData = [NSData dataWithContentsOfURL:url];
//1.3 轉換圖片
UIImage *image = [UIImage imageWithData:imageData];
NSLog(@"download----%@",[NSThread currentThread]);
//更新UI
// dispatch_async(dispatch_get_main_queue(), ^{
dispatch_sync(dispatch_get_main_queue(), ^{
self.imageView.image = image;
NSLog(@"UI----%@",[NSThread currentThread]);
});
});
常用函數(shù)
/*
第一個參數(shù):DISPATCH_TIME_NOW 從現(xiàn)在開始計算時間
第二個參數(shù):延遲的時間 2.0 GCD時間單位:納秒
第三個參數(shù):隊列
*/
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), queue, ^{
NSLog(@"GCD----%@",[NSThread currentThread]);
});
//一次性代碼
//不能放在懶加載中的,應用場景:單例模式
-(void)once
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"---once----");
});
}
柵欄函數(shù)
//0.獲得全局并發(fā)隊列
//柵欄函數(shù)不能使用全局并發(fā)隊列
//dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t queue = dispatch_queue_create("download", DISPATCH_QUEUE_CONCURRENT);
//1.異步函數(shù)
dispatch_async(queue, ^{
for (NSInteger i = 0; i<100; i++) {
NSLog(@"download1-%zd-%@",i,[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (NSInteger i = 0; i<100; i++) {
NSLog(@"download2-%zd-%@",i,[NSThread currentThread]);
}
});
//柵欄函數(shù)
dispatch_barrier_async(queue, ^{
NSLog(@"+++++++++++++++++++++++++++++");
});
dispatch_async(queue, ^{
for (NSInteger i = 0; i<100; i++) {
NSLog(@"download3-%zd-%@",i,[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (NSInteger i = 0; i<100; i++) {
NSLog(@"download4-%zd-%@",i,[NSThread currentThread]);
}
});
download4 download3 會在 download1 download2后執(zhí)行
快速迭代
//開子線程和主線程一起完成遍歷任務,任務的執(zhí)行時并發(fā)的
-(void)applyDemo
{
/*
第一個參數(shù):遍歷的次數(shù)
第二個參數(shù):隊列(并發(fā)隊列)
第三個參數(shù):index 索引
*/
dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index) {
NSLog(@"%zd---%@",index,[NSThread currentThread]);
});
}
GCD另一種寫法
/*
第一個參數(shù):隊列
第二個參數(shù):參數(shù)
第三個參數(shù):要調用的函數(shù)的名稱
*/
dispatch_async_f(dispatch_get_global_queue(0, 0), NULL, task);
dispatch_async_f(dispatch_get_global_queue(0, 0), NULL, task);
dispatch_async_f(dispatch_get_global_queue(0, 0), NULL, task);
隊列組
第一種
//1.創(chuàng)建隊列
dispatch_queue_t queue =dispatch_get_global_queue(0, 0);
//2.創(chuàng)建隊列組
dispatch_group_t group = dispatch_group_create();
//3.異步函數(shù)
/*
1)封裝任務
2)把任務添加到隊列中
dispatch_async(queue, ^{
NSLog(@"1----%@",[NSThread currentThread]);
});
*/
/*
1)封裝任務
2)把任務添加到隊列中
3)會監(jiān)聽任務的執(zhí)行情況,通知group
*/
dispatch_group_async(group, queue, ^{
NSLog(@"1----%@",[NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
NSLog(@"2----%@",[NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
NSLog(@"3----%@",[NSThread currentThread]);
});
//攔截通知,當隊列組中所有的任務都執(zhí)行完畢的時候回進入到下面的方法
dispatch_group_notify(group, queue, ^{
NSLog(@"-------dispatch_group_notify-------");
});
// NSLog(@"----end----");
第二種
//1.創(chuàng)建隊列
dispatch_queue_t queue =dispatch_get_global_queue(0, 0);
//2.創(chuàng)建隊列組
dispatch_group_t group = dispatch_group_create();
//3.在該方法后面的異步任務會被納入到隊列組的監(jiān)聽范圍,進入群組
//dispatch_group_enter|dispatch_group_leave 必須要配對使用
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"1----%@",[NSThread currentThread]);
//離開群組
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"2----%@",[NSThread currentThread]);
//離開群組
dispatch_group_leave(group);
});
//攔截通知
//問題?該方法是阻塞的嗎? 內部本身是異步的
// dispatch_group_notify(group, queue, ^{
// NSLog(@"-------dispatch_group_notify-------");
// });
//等待.死等. 直到隊列組中所有的任務都執(zhí)行完畢之后才能執(zhí)行
//阻塞的
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"----end----");
單利實現(xiàn)
ARC下
/0.提供全局變量
static XMGTool *_instance;
//1.alloc-->allocWithZone
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
//加互斥鎖解決多線程訪問安全問題
// @synchronized(self) {
// if (_instance == nil) {
// _instance = [super allocWithZone:zone];
// }
// }
//本身就是線程安全的
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
//2.提供類方法
+(instancetype)shareTool
{
return [[self alloc]init];
}
//3.嚴謹
-(id)copyWithZone:(NSZone *)zone
{
return _instance;
}
-(id)mutableCopyWithZone:(NSZone *)zone
{
return _instance;
}
MRC下:
#if __has_feature(objc_arc)
//條件滿足 ARC
#else
// MRC
-(oneway void)release
{
}
-(instancetype)retain
{
return _instance;
}
//習慣
-(NSUInteger)retainCount
{
return MAXFLOAT;
}
#endif
NSOperation
基本使用
//1.創(chuàng)建操作,封裝任務
/*
第一個參數(shù):目標對象 self
第二個參數(shù):調用方法的名稱
第三個參數(shù):前面方法需要接受的參數(shù) nil
*/
NSInvocationOperation *op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download1) object:nil];
NSInvocationOperation *op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download2) object:nil];
NSInvocationOperation *op3 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download3) object:nil];
//2.啟動|執(zhí)行操作
[op1 start];
[op2 start];
[op3 start];
上面的使用運行在主線程
//1.創(chuàng)建操作
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"1----%@",[NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"2----%@",[NSThread currentThread]);
}];
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"3----%@",[NSThread currentThread]);
}];
//追加任務
//注意:如果一個操作中的任務數(shù)量大于1,那么會開子線程并發(fā)執(zhí)行任務(就是此列加block任務開線程,不加跟上面一樣)
//注意:不一定是子線程,有可能是主線程
[op3 addExecutionBlock:^{
NSLog(@"4---%@",[NSThread currentThread]);
}];
[op3 addExecutionBlock:^{
NSLog(@"5---%@",[NSThread currentThread]);
}];
[op3 addExecutionBlock:^{
NSLog(@"6---%@",[NSThread currentThread]);
}];
//2.啟動
[op1 start];
[op2 start];
[op3 start];
NSOperationQueue
//1.創(chuàng)建操作,封裝任務
/*
第一個參數(shù):目標對象 self
第二個參數(shù):調用方法的名稱
第三個參數(shù):前面方法需要接受的參數(shù) nil
*/
NSInvocationOperation *op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download1) object:nil];
NSInvocationOperation *op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download2) object:nil];
NSInvocationOperation *op3 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download3) object:nil];
//2.創(chuàng)建隊列
/*
GCD:
串行類型:create & 主隊列
并發(fā)類型:create & 全局并發(fā)隊列
NSOperation:
主隊列: [NSOperationQueue mainQueue] 和GCD中的主隊列一樣,串行隊列
非主隊列: [[NSOperationQueue alloc]init] 非常特殊(同時具備并發(fā)和串行的功能)
//默認情況下,非主隊列是并發(fā)隊列
*/
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//3.添加操作到隊列中
[queue addOperation:op1]; //內部已經調用了[op1 start]
[queue addOperation:op2];
[queue addOperation:op3];
block的那種用法一樣