同步異步串行并行
- 同步串行:不開啟線程
- 同步并行:不開啟線程
- 異步串行:最多開啟一個線程
- 異步并行:開啟線程
- 同步:不開啟線程喧务,并將添加信號鎖篙螟。同步會阻塞當前線程
- 異步:可以開啟線程
- 串行:任務(wù)一個一個執(zhí)行
- 并行:任務(wù)不用一個一個執(zhí)行
線程死鎖
在一個線程中一個串行隊列中兩個同步任務(wù)相互等待出現(xiàn)線程死鎖
- (void)test1{
dispatch_queue_t queueSerial = dispatch_queue_create("queueSerial", DISPATCH_QUEUE_SERIAL);
/** 同步隊列中兩個任務(wù)相互等待 */
dispatch_sync(queueSerial, ^{
dispatch_sync(queueSerial, ^{
});
});
}
- (void)test2{
/** 主隊列中兩個任務(wù)相互等待 */
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"22");
});
}
- (void)test3{
/** 兩個隊列中任務(wù)相互等待 */
dispatch_queue_t queueSerialOne = dispatch_queue_create("queueSerial", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queueSerialTwo = dispatch_queue_create("queueSerial", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queueSerialOne, ^{
dispatch_sync(queueSerialTwo, ^{
dispatch_sync(queueSerialOne, ^{
});
});
});
}
死鎖解釋:同步開啟信號量题山,信號量的++被壓到了最下面
dispatch_async(queue, ^{
dispatch_semaphore_signal(semaphore);
});
延遲執(zhí)行
默認方式是異步御板,使用主要隊列會在主線程中執(zhí)行
使用串行隊列會開啟線程
- (void)test4{
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC));
dispatch_queue_t queueSerialOne = dispatch_queue_create("queueSerial", DISPATCH_QUEUE_SERIAL);
dispatch_after(time, queueSerialOne, ^{
});
}
組
dispatch_group_t: 可以阻塞當前線程特咆,當所有任務(wù)完成時在往下執(zhí)行
dispatch_group_notify: 可以不阻塞當前線程
- (void)test5{
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_async(group, queue, ^{
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
}
- (void)test6{
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(group, queue, ^{
});
dispatch_group_notify(group, queue, ^{
});
}
多次執(zhí)行
dispatch_apply: 會阻塞當前線程
- (void)test7{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(10, queue, ^(size_t i) {
});
}
隊列特有數(shù)據(jù)
- (void)test8{
dispatch_queue_t queueA = dispatch_queue_create("queueA", NULL);
dispatch_queue_t queueB = dispatch_queue_create("queueB", NULL);
dispatch_set_target_queue(queueB, queueA);
static int kQeueueSpecific;
CFStringRef queueSpecificValue = CFSTR("queueA");
dispatch_queue_set_specific(queueA, &kQeueueSpecific, (void *)queueSpecificValue, (dispatch_function_t)CFRelease);
dispatch_sync(queueB, ^{
dispatch_block_t block = ^{
NSLog(@"2222");
};
CFStringRef retrievedValue = dispatch_get_specific(&kQeueueSpecific);
if (retrievedValue) {
block();
}else{
dispatch_sync(queueA, block);
}
});
}
規(guī)律小結(jié)
- 串行隊列中通過異步開啟線程患民,最多只能開啟一個
- 串行隊列的末尾有信號量,需要等待執(zhí)行完成后衣赶,才能往下一個執(zhí)行
- 在一個線程中一個串行隊列中兩個同步任務(wù)相互等待出現(xiàn)線程死鎖诊赊,信號量的++被壓到了最下面
- 異步?jīng)Q定是否開啟線程,并且是否開啟信號量
- 串行隊列按照順序執(zhí)行
- 同步下任務(wù)相互等待會造成線程死鎖
NSOpetation
- (void)opration{
// 在當前線程使用子類 NSInvocationOperation
[self useInvocationOperation];
// 在其他線程使用子類 NSInvocationOperation
// [NSThread detachNewThreadSelector:@selector(useInvocationOperation) toTarget:self withObject:nil];
// 在當前線程使用 NSBlockOperation
// [self useBlockOperation];
// 使用 NSBlockOperation 的 AddExecutionBlock: 方法
// [self useBlockOperationAddExecutionBlock];
// 使用自定義繼承自 NSOperation 的子類
// [self useCustomOperation];
// 使用addOperation: 添加操作到隊列中
// [self addOperationToQueue];
// 使用 addOperationWithBlock: 添加操作到隊列中
// [self addOperationWithBlockToQueue];
// 設(shè)置最大并發(fā)操作數(shù)(MaxConcurrentOperationCount)
// [self setMaxConcurrentOperationCount];
// 設(shè)置優(yōu)先級
// [self setQueuePriority];
// 添加依賴
// [self addDependency];
// 線程間的通信
// [self communication];
// 完成操作
// [self completionBlock];
// 不考慮線程安全
// [self initTicketStatusNotSave];
// 考慮線程安全
// [self initTicketStatusSave];
}
使用子類 NSInvocationOperation
- (void)useInvocationOperation {
// 1.創(chuàng)建 NSInvocationOperation 對象
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task1) object:nil];
// 2.調(diào)用 start 方法開始執(zhí)行操作
[op start];
}
使用子類 NSBlockOperation
- (void)useBlockOperation {
// 1.創(chuàng)建 NSBlockOperation 對象
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@", [NSThread currentThread]); // 打印當前線程
}
}];
// 2.調(diào)用 start 方法開始執(zhí)行操作
[op start];
}
使用子類 NSBlockOperation
- 使用子類 NSBlockOperation
- 調(diào)用方法 AddExecutionBlock:
- (void)useBlockOperationAddExecutionBlock {
// 1.創(chuàng)建 NSBlockOperation 對象
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@", [NSThread currentThread]); // 打印當前線程
}
}];
// 2.添加額外的操作
[op addExecutionBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"2---%@", [NSThread currentThread]); // 打印當前線程
}
}];
[op addExecutionBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"3---%@", [NSThread currentThread]); // 打印當前線程
}
}];
[op addExecutionBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"4---%@", [NSThread currentThread]); // 打印當前線程
}
}];
[op addExecutionBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"5---%@", [NSThread currentThread]); // 打印當前線程
}
}];
[op addExecutionBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"6---%@", [NSThread currentThread]); // 打印當前線程
}
}];
[op addExecutionBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"7---%@", [NSThread currentThread]); // 打印當前線程
}
}];
[op addExecutionBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"8---%@", [NSThread currentThread]); // 打印當前線程
}
}];
// 3.調(diào)用 start 方法開始執(zhí)行操作
[op start];
}
使用自定義繼承自 NSOperation 的子類
- (void)useCustomOperation {
// 1.創(chuàng)建 YSCOperation 對象
YSCOperation *op = [[YSCOperation alloc] init];
// 2.調(diào)用 start 方法開始執(zhí)行操作
[op start];
}
使用 addOperation: 將操作加入到操作隊列中
- (void)addOperationToQueue {
// 1.創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 2.創(chuàng)建操作
// 使用 NSInvocationOperation 創(chuàng)建操作1
NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task1) object:nil];
// 使用 NSInvocationOperation 創(chuàng)建操作2
NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task2) object:nil];
// 使用 NSBlockOperation 創(chuàng)建操作3
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"3---%@", [NSThread currentThread]); // 打印當前線程
}
}];
[op3 addExecutionBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"4---%@", [NSThread currentThread]); // 打印當前線程
}
}];
// 3.使用 addOperation: 添加所有操作到隊列中
[queue addOperation:op1]; // [op1 start]
[queue addOperation:op2]; // [op2 start]
[queue addOperation:op3]; // [op3 start]
}
使用 addOperationWithBlock: 將操作加入到操作隊列中
- (void)addOperationWithBlockToQueue {
// 1.創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 2.使用 addOperationWithBlock: 添加操作到隊列中
[queue addOperationWithBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@", [NSThread currentThread]); // 打印當前線程
}
}];
[queue addOperationWithBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"2---%@", [NSThread currentThread]); // 打印當前線程
}
}];
[queue addOperationWithBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"3---%@", [NSThread currentThread]); // 打印當前線程
}
}];
}
設(shè)置 MaxConcurrentOperationCount(最大并發(fā)操作數(shù))
- (void)setMaxConcurrentOperationCount {
// 1.創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 2.設(shè)置最大并發(fā)操作數(shù)
queue.maxConcurrentOperationCount = 1; // 串行隊列
// queue.maxConcurrentOperationCount = 2; // 并發(fā)隊列
// queue.maxConcurrentOperationCount = 8; // 并發(fā)隊列
// 3.添加操作
[queue addOperationWithBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@", [NSThread currentThread]); // 打印當前線程
}
}];
[queue addOperationWithBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"2---%@", [NSThread currentThread]); // 打印當前線程
}
}];
[queue addOperationWithBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"3---%@", [NSThread currentThread]); // 打印當前線程
}
}];
[queue addOperationWithBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"4---%@", [NSThread currentThread]); // 打印當前線程
}
}];
}
設(shè)置優(yōu)先級
- 就緒狀態(tài)下府瞄,優(yōu)先級高的會優(yōu)先執(zhí)行碧磅,但是執(zhí)行時間長短并不是一定的,所以優(yōu)先級高的并不是一定會先執(zhí)行完畢
- (void)setQueuePriority
{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 2; i++) {
NSLog(@"1-----%@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:2];
}
}];
[op1 setQueuePriority:(NSOperationQueuePriorityVeryLow)];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 2; i++) {
NSLog(@"2-----%@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:2];
}
}];
[op2 setQueuePriority:(NSOperationQueuePriorityVeryHigh)];
[queue addOperation:op1];
[queue addOperation:op2];
}
操作依賴
- 使用方法:addDependency:
- (void)addDependency {
// 1.創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 2.創(chuàng)建操作
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@", [NSThread currentThread]); // 打印當前線程
}
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"2---%@", [NSThread currentThread]); // 打印當前線程
}
}];
// 3.添加依賴
[op2 addDependency:op1]; // 讓op2 依賴于 op1遵馆,則先執(zhí)行op1鲸郊,在執(zhí)行op2
// 4.添加操作到隊列中
[queue addOperation:op1];
[queue addOperation:op2];
}
線程間通信
- (void)communication {
// 1.創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
// 2.添加操作
[queue addOperationWithBlock:^{
// 異步進行耗時操作
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@", [NSThread currentThread]); // 打印當前線程
}
// 回到主線程
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// 進行一些 UI 刷新等操作
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"2---%@", [NSThread currentThread]); // 打印當前線程
}
}];
}];
}
完成操作 completionBlock
- (void)completionBlock {
// 1.創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 2.創(chuàng)建操作
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@", [NSThread currentThread]); // 打印當前線程
}
}];
// 3.添加完成操作
op1.completionBlock = ^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"2---%@", [NSThread currentThread]); // 打印當前線程
}
};
// 4.添加操作到隊列中
[queue addOperation:op1];
}
線程安全
- 非線程安全:不使用 NSLock
- 初始化火車票數(shù)量、賣票窗口(非線程安全)团搞、并開始賣票
- (void)initTicketStatusNotSave {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印當前線程
self.ticketSurplusCount = 50;
// 1.創(chuàng)建 queue1,queue1 代表北京火車票售賣窗口
NSOperationQueue *queue1 = [[NSOperationQueue alloc] init];
queue1.maxConcurrentOperationCount = 1;
// 2.創(chuàng)建 queue2,queue2 代表上貉贤火車票售賣窗口
NSOperationQueue *queue2 = [[NSOperationQueue alloc] init];
queue2.maxConcurrentOperationCount = 1;
// 3.創(chuàng)建賣票操作 op1
__weak typeof(self) weakSelf = self;
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
[weakSelf saleTicketNotSafe];
}];
// 4.創(chuàng)建賣票操作 op2
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
[weakSelf saleTicketNotSafe];
}];
// 5.添加操作,開始賣票
[queue1 addOperation:op1];
[queue2 addOperation:op2];
}
售賣火車票(非線程安全)
- (void)saleTicketNotSafe {
while (1) {
if (self.ticketSurplusCount > 0) {
//如果還有票逻恐,繼續(xù)售賣
self.ticketSurplusCount--;
NSLog(@"%@", [NSString stringWithFormat:@"剩余票數(shù):%d 窗口:%@", self.ticketSurplusCount, [NSThread currentThread]]);
[NSThread sleepForTimeInterval:0.2];
} else {
NSLog(@"所有火車票均已售完");
break;
}
}
}
線程安全:使用 NSLock 加鎖
- 初始化火車票數(shù)量像吻、賣票窗口(線程安全)、并開始賣票
- (void)initTicketStatusSave {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印當前線程
self.ticketSurplusCount = 50;
self.lock = [[NSLock alloc] init];
// 1.創(chuàng)建 queue1,queue1 代表北京火車票售賣窗口
NSOperationQueue *queue1 = [[NSOperationQueue alloc] init];
queue1.maxConcurrentOperationCount = 1;
// 2.創(chuàng)建 queue2,queue2 代表上焊绰。火車票售賣窗口
NSOperationQueue *queue2 = [[NSOperationQueue alloc] init];
queue2.maxConcurrentOperationCount = 1;
// 3.創(chuàng)建賣票操作 op1
__weak typeof(self) weakSelf = self;
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
[weakSelf saleTicketSafe];
}];
// 4.創(chuàng)建賣票操作 op2
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
[weakSelf saleTicketSafe];
}];
// 5.添加操作拨匆,開始賣票
[queue1 addOperation:op1];
[queue2 addOperation:op2];
}
售賣火車票(線程安全)
- (void)saleTicketSafe {
while (1) {
// 加鎖
[self.lock lock];
if (self.ticketSurplusCount > 0) {
//如果還有票,繼續(xù)售賣
self.ticketSurplusCount--;
NSLog(@"%@", [NSString stringWithFormat:@"剩余票數(shù):%d 窗口:%@", self.ticketSurplusCount, [NSThread currentThread]]);
[NSThread sleepForTimeInterval:0.2];
}
// 解鎖
[self.lock unlock];
if (self.ticketSurplusCount <= 0) {
NSLog(@"所有火車票均已售完");
break;
}
}
}
/**
* 任務(wù)1
*/
- (void)task1 {
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@", [NSThread currentThread]); // 打印當前線程
}
}
/**
* 任務(wù)2
*/
- (void)task2 {
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"2---%@", [NSThread currentThread]); // 打印當前線程
}
}
參考:
http://www.cocoachina.com/ios/20170801/20089.html
http://www.reibang.com/p/5e6300cb3fc5
http://www.reibang.com/p/93c1012c2e48
http://www.reibang.com/p/4b1d77054b35