子线程并行
//GCD开一个子线程
//系统 并行队列
//获得全局队列 (并行队列)
//参数1.设置队列优先级别
//参数2.系统预留参数设置为0
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(globalQueue, ^{
NSLog(@"是否是主线程a =0 %d", [NSThread isMainThread]);
//回到主线程
dispatch_async(dispatch_get_main_queue(), ^{
self.view.backgroundColor = [UIColor redColor];
});
});
串行 主线程
//GCD串行 主线程
//串行队列
//调用系统的主线程实现串行队列
dispatch_queue_t mainQueue = dispatch_get_main_queue();
//执行队列任务
//参数1.设置队列
dispatch_async(mainQueue, ^{
NSLog(@"是否是主线程a =1 %d", [NSThread isMainThread]);
});
dispatch_async(mainQueue, ^{
NSLog(@"是否是主线程b =1 %d", [NSThread isMainThread]);
});
dispatch_async(mainQueue, ^{
NSLog(@"是否是主线程c =1 %d", [NSThread isMainThread]);
});
串行队列 子线程
//自定义串行队列 子线程
//参数1.队列标识符 (串行队列)
//参数2.设置队列类型
dispatch_queue_t serialOueue = dispatch_queue_create("queueName", DISPATCH_QUEUE_SERIAL);
////执行队列任务
dispatch_async(serialOueue, ^{
NSLog(@"是否是主线程a =0 %d", [NSThread isMainThread]);
});
dispatch_async(serialOueue, ^{
NSLog(@"是否是主线程b =0 %d", [NSThread isMainThread]);
});
dispatch_async(serialOueue, ^{
NSLog(@"是否是主线程c =0 %d", [NSThread isMainThread]);
});
并行队列 子线程
//系统 并行队列 子线程
// 1.创建并发队列
dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
// 2.向队列中添加任务
dispatch_async(queue, ^{ //
NSLog(@"是否是主线程a =0 %d", [NSThread isMainThread]);
});
dispatch_async(queue, ^{
NSLog(@"是否是主线程b =0 %d", [NSThread isMainThread]);
});
dispatch_async(queue, ^{
NSLog(@"是否是主线程c =0 %d", [NSThread isMainThread]);
});
栅栏函数 控制执行顺序 避免数据竞争
/*
GCD栅栏函数作用:
1.在它前面的任务执行结束后它才执行,它后面的任务要等它执行完成后才会开始执行。
2.避免数据竞争
*/
//GCD栅栏函数
//http://www.jianshu.com/p/a5048100e843
//* 与dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL)(串行队列)一起使用,会创建一个线程,barrier前后的任务串行执行
//* 与dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT)(自定义并发队列)一起使用,创建多个线程,barrier前后的任务都是并行执行.
//栅栏函数
dispatch_queue_t queue = dispatch_queue_create("12312312", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"是否是主线程a =0 %d", [NSThread isMainThread]);
for (int i = 0; i < 10; i++) {
NSLog(@"aaaaa");
}
});
dispatch_async(queue, ^{
NSLog(@"是否是主线程b =0 %d", [NSThread isMainThread]);
for (int i = 0; i < 10; i++) {
NSLog(@"bbbbbbbbbbbb");
}
});
dispatch_barrier_async(queue, ^{
NSLog(@"----barrier-----%@", [NSThread currentThread]);
NSLog(@"是否是主线程barrier =0 %d", [NSThread isMainThread]);
for (int i = 0; i < 10; i++) {
NSLog(@"barrier=========barrier");
}
});
dispatch_async(queue, ^{
NSLog(@"是否是主线程c =0 %d", [NSThread isMainThread]);
for (int i = 0; i < 10; i++) {
NSLog(@"cccccccccccccccccccc");
}
});
dispatch_async(queue, ^{
NSLog(@"是否是主线程d =0 %d", [NSThread isMainThread]);
for (int i = 0; i < 10; i++) {
NSLog(@"dddddddddddddddddddddddddddd");
}
});
多线程分组
///////////////////////////////////////////多线程分组的写法
http://blog.csdn.net/wangzitao126/article/details/43195533
博客
#第一种
dispatch_group_t group = dispatch_group_create();
// 某个任务放进 group
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
// 任务代码1
dispatch_group_enter(group);//加入组
执行网络请求后处理数据
dispatch_group_leave(group);//离开组
});
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
// 任务代码2
dispatch_group_enter(group);//加入组
执行网络请求后处理数据
dispatch_group_leave(group);//离开组
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 任务全部完成处理 加入几次就要离开几次 这个回调才会被执行
NSLog(@"isover");
});
创建一个任务组,然后将异步操作放进组里面,在最后用notify 告知所有任务完成,并做相应处理,一般来说都是在主线程里面刷新UI来提示用户了。你如果不依赖UI放进子线程里面也是没有问题的。当然group同步的方式还有其他
#第二种
dispatch_group_t group = dispatch_group_create();
// 某个任务放进 group
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
// 任务代码1
dispatch_group_enter(group);//加入组
// 任务代码i 假定任务 是异步执行block回调
// block 回调执行
dispatch_group_leave(group);//离开组
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_async(dispatch_get_main_queue(), ^{
// 主线程处理
// 任务全部完成处理
NSLog(@"isover");
});
首先我们异步执行,因为dispatch_group_wait函数是阻塞的,for里面安排了三个任务,这三个任务都是加载,在任务开始前 调用 enter,任务完成时调用leave,wait函数一直阻塞,直到它发现group里面的任务全部leave,它才放弃阻塞(任务全部完成),然后我们在主线程更新UI告知用户.
# Swift
let group = DispatchGroup()
let queue = DispatchQueue.global()
queue.async(group: group) {
group.enter()
// 耗时操作
group.leave()
}
group.notify(queue: DispatchQueue.main) {
//异步操作都完成之后,主线程操作
}
GCD信号量
//GCD信号量
//控制线程并发数
//创建信号量 这里设置最大数量是5
dispatch_semaphore_t sema = dispatch_semaphore_create(5);
for (int i = 0; i < 100; i++) {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);//在这里添加网络请求 但是是等待的 这里信号量先是=0 下边+1之后 执行dispatch_semaphore_wait内部实现之后 信号量-1
//创建任务
dispatch_async(queue, ^{
NSLog(@"是否是主线程a = %d", [NSThread isMainThread]);
NSLog(@"%i",i);
// sleep(2);
// 操作
dispatch_semaphore_signal(sema); //这里信号量+1 上边的任务会执行
});
}
//dispatch_semaphore_wait:信号等待,它像一个安保,比如小区规定最多只能进入3辆车,而进入一辆车后名额就会减少一个,当剩下的名额为0的时候,再有汽车说要进去时,就只能在外面等待了,直到有名额闲置出来了,才能开进小区。
//dispatch_semaphore_signal:信号释放,当有一辆车从小区出来时,就腾出来了一个名额。
#利用信号量实现->异步执行->同步处理
按照:任务1 -> 任务2 -> 任务3 的执行顺序执行
dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_semaphore_t sema = dispatch_semaphore_create(1);
// 2.向队列中添加任务
dispatch_async(queue, ^{
//等待(sema信号量==0的时候 线程等待 不往下执行)
//初始化的时候 sema信号量==1 这里不会出现等待的情况
//但是执行完dispatch_semaphore_wait 相当于执行了sema--(信号量-1)的操作
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
//任务1->异步返回结果
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager POST:@"url" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
dispatch_semaphore_signal(sema);//请求成功 sema++(信号量+1)
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
dispatch_semaphore_signal(sema);//请求失败 sema++(信号量+1)
}];
});
dispatch_async(queue, ^{
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
//任务2->异步返回结果之后
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager POST:@"url" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
dispatch_semaphore_signal(sema);//请求成功
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
dispatch_semaphore_signal(sema);//请求失败
}];
});
dispatch_async(queue, ^{
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
//任务3->异步返回结果之后
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager POST:@"url" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
dispatch_semaphore_signal(sema);//请求成功
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
dispatch_semaphore_signal(sema);//请求失败
}];
});
#典型的例子就是卖火车票(查询同一趟车次余票) 多个窗口(相当于并发多个线程)
这样才是一个安全的线程
//火车票数量
@property (nonatomic, assign)int ticketNum;
//声明信号量
@property (nonatomic, strong)dispatch_semaphore_t sema;
//GCD信号量
//控制线程并发数
//创建信号量 这里设置最大数量是1
self.sema = dispatch_semaphore_create(1);
self.ticketNum = 10;//车票数量
dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
// 向队列中添加任务
dispatch_async(queue, ^{
for (int i = 0; i < 5; i++) {
[self diminishingNum:1];
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 4; i++) {
[self diminishingNum:2];
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 3; i++) {
[self diminishingNum:3];
}
});
//卖出火车票 执行一次就减少一张车票
-(void)diminishingNum:(int)n
{
NSLog(@"前self.ticketNum====%d ->任务n==%d", self.ticketNum, n);
dispatch_semaphore_wait(self.sema, DISPATCH_TIME_FOREVER);//在这里添加网络请求 但是是等待的 这里信号量先是=0 下边+1之后 执行dispatch_semaphore_wait内部实现之后 信号量-1
if (self.ticketNum == 0) {
NSLog(@"车票已卖完===%@", [NSString stringWithFormat:@"剩余票数:%d 窗口:%@ ->任务n==%d", self.ticketNum, [NSThread currentThread], n]);
}else{
sleep(2);//处理车票或者网络请求 是否卖出
self.ticketNum--;//这里减少一张车票
NSLog(@"后self.ticketNum====%d ->任务n==%d", self.ticketNum, n);
NSLog(@"%@", [NSString stringWithFormat:@"剩余票数:%d 窗口:%@ ->任务n==%d", self.ticketNum, [NSThread currentThread], n]);
}
dispatch_semaphore_signal(self.sema); //这里信号量+1 上边的任务会执行
}
打印
前self.ticketNum====10 ->任务n==1
前self.ticketNum====10 ->任务n==3
前self.ticketNum====10 ->任务n==2
后self.ticketNum====9 ->任务n==1
剩余票数:9 窗口:<NSThread: 0x60000149df00>{number = 9, name = (null)} ->任务n==1
前self.ticketNum====9 ->任务n==1
后self.ticketNum====8 ->任务n==3
剩余票数:8 窗口:<NSThread: 0x6000014dc540>{number = 6, name = (null)} ->任务n==3
前self.ticketNum====8 ->任务n==3
后self.ticketNum====7 ->任务n==2
剩余票数:7 窗口:<NSThread: 0x600001498f40>{number = 10, name = (null)} ->任务n==2
前self.ticketNum====7 ->任务n==2
后self.ticketNum====6 ->任务n==1
剩余票数:6 窗口:<NSThread: 0x60000149df00>{number = 9, name = (null)} ->任务n==1
前self.ticketNum====6 ->任务n==1
后self.ticketNum====5 ->任务n==3
剩余票数:5 窗口:<NSThread: 0x6000014dc540>{number = 6, name = (null)} ->任务n==3
前self.ticketNum====5 ->任务n==3
后self.ticketNum====4 ->任务n==2
剩余票数:4 窗口:<NSThread: 0x600001498f40>{number = 10, name = (null)} ->任务n==2
前self.ticketNum====4 ->任务n==2
后self.ticketNum====3 ->任务n==1
剩余票数:3 窗口:<NSThread: 0x60000149df00>{number = 9, name = (null)} ->任务n==1
[MapViewController.m:223行] 前self.ticketNum====3 ->任务n==1
后self.ticketNum====2 ->任务n==3
剩余票数:2 窗口:<NSThread: 0x6000014dc540>{number = 6, name = (null)} ->任务n==3
[MapViewController.m:230行] 后self.ticketNum====1 ->任务n==2
剩余票数:1 窗口:<NSThread: 0x600001498f40>{number = 10, name = (null)} ->任务n==2
前self.ticketNum====1 ->任务n==2
后self.ticketNum====0 ->任务n==1
剩余票数:0 窗口:<NSThread: 0x60000149df00>{number = 9, name = (null)} ->任务n==1
前self.ticketNum====0 ->任务n==1
车票已卖完===剩余票数:0 窗口:<NSThread: 0x600001498f40>{number = 10, name = (null)} ->任务n==2
车票已卖完===剩余票数:0 窗口:<NSThread: 0x60000149df00>{number = 9, name = (null)} ->任务n==1
NSLock线程锁
/*
NSLock *lock = [[NSLock alloc] init];
[lock lock];//加锁
[self 方法];//执行调用方法
[lock unlock];//解锁
*/
NSLock *lock = [[NSLock alloc] init];
dispatch_queue_t globalQueue = dispatch_queue_create("aaa", DISPATCH_QUEUE_SERIAL);
dispatch_async(globalQueue, ^{
NSLog(@"是否是主线程11 =0 %d", [NSThread isMainThread]);
[lock lock];
sleep(3);
NSLog(@"11111");
[lock unlock];
});
dispatch_async(globalQueue, ^{
NSLog(@"是否是主线程222 =0 %d", [NSThread isMainThread]);
[lock lock];
sleep(3);
NSLog(@"222222");
[lock unlock];
});
dispatch_async(globalQueue, ^{
NSLog(@"是否是主线程333 =0 %d", [NSThread isMainThread]);
[lock lock];
sleep(3);
NSLog(@"333333");
[lock unlock];
});
打印
是否是主线程11 =0 0
11111
是否是主线程222 =0 0
222222
是否是主线程333 =0 0
333333
#以上是没问题的 下面说一下死锁现象
NSLock死锁现象
简单的说就是(同一个线程中不能加锁两次或多次,要加锁->解锁->加锁->解锁...)
[lock lock];
[lock lock];//死锁了 往下的代码不会执行了
不会执行
.
.
.
[lock unlock];//不会执行
针对火车票的线程锁
效率上 dispatch_semaphore > NSLock > @synchronized
NSLock
-(void)diminishingNum:(int)n
{//self.lock1 = [[NSLock alloc] init];
NSLog(@"前self.ticketNum====%d ->任务n==%d", self.ticketNum, n);
[self.lock1 lock];
if (self.ticketNum == 0) {
NSLog(@"车票已卖完===%@", [NSString stringWithFormat:@"剩余票数:%d 窗口:%@ ->任务n==%d", self.ticketNum, [NSThread currentThread], n]);
}else{
sleep(2);//处理车票或者网络请求 是否卖出
self.ticketNum--;//这里减少一张车票
NSLog(@"后self.ticketNum====%d ->任务n==%d", self.ticketNum, n);
NSLog(@"%@", [NSString stringWithFormat:@"剩余票数:%d 窗口:%@ ->任务n==%d", self.ticketNum, [NSThread currentThread], n]);
}
[self.lock1 unlock];
}
@synchronized用法简单 但是性能比较低效消耗性能
-(void)diminishingNum:(int)n
{
NSLog(@"前self.ticketNum====%d ->任务n==%d", self.ticketNum, n);
@synchronized (self) {
if (self.ticketNum == 0) {
NSLog(@"车票已卖完===%@", [NSString stringWithFormat:@"剩余票数:%d 窗口:%@ ->任务n==%d", self.ticketNum, [NSThread currentThread], n]);
}else{
sleep(2);//处理车票或者网络请求 是否卖出
self.ticketNum--;//这里减少一张车票
NSLog(@"后self.ticketNum====%d ->任务n==%d", self.ticketNum, n);
NSLog(@"%@", [NSString stringWithFormat:@"剩余票数:%d 窗口:%@ ->任务n==%d", self.ticketNum, [NSThread currentThread], n]);
}
}
}
网友评论