NSThread三种创建方式:需要手动管理线程
• init创建 ,start启动
• detachNewThreadSelector创建好之后自动启动
• performSelectorInBackground创建好之后直接启动
init创建
/**
init 方式创建
1. 默认开启新线程
2. 需要 start 启动
*/
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadMethodOne:) object:nil];
[thread start];
/**
init block方式
1. 默认开启新线程
*/
NSThread *thread1 = [[NSThread alloc] initWithBlock:^{
NSLog(@"block线程执行了%@",[NSThread currentThread]);
}];
NSThread 类方法 detachNewThreadSelector
/**
类方法创建
1. 默认开启新线程
2. 创建及启动
*/
[NSThread detachNewThreadSelector:@selector(threadMethodOne:) toTarget:self withObject:nil];
NSThread 隐式创建 performSelectorInBackground
/**
隐式创建
1. 默认开启新线程
2. 创建后自动启动
*/
[self performSelectorInBackground:@selector(threadMethodOne:) withObject:nil];
//主线程
[self performSelectorOnMainThread:@selector(threadMethodOne:) withObject:nil waitUntilDone:nil];
NSThread 相关类方法
//返回当前线程
[NSThread currentThread];
//阻塞休眠
[NSThread sleepForTimeInterval:2];
//退出线程
[NSThread exit];
//判断当前线程是否为主线程
[NSThread isMainThread];
//判断当前线程是否是多线程
[NSThread isMultiThreaded];
//主线程的对象
NSThread *mainThread = [NSThread mainThread];
NSThread 属性
NSThread *thread = [[NSThread alloc] init];
//线程是否在执行
thread.isExecuting;
//线程是否被取消
thread.isCancelled;
//线程是否完成
thread.isFinished;
//是否是主线程
thread.isMainThread;
//线程的优先级,取值范围0.0到1.0,默认优先级0.5,1.0表示最高优先级,优先级高,CPU调度的频率高
thread.threadPriority;
GCD 的使用
• GCD会自动利用更多的CPU内核
• GCD自动管理线程的生命周期(创建线程,调度任务,销毁线程等)
• 程序员只需要告诉 GCD 想要如何执行什么任务,不需要编写任何线程管理代码
• sync : 同步,不开启新线程
• async : 异步 , 开启新线程
• 队列: 装载线程任务的队形结构。(系统以先进先出的方式调度队列中的任务执行)。在GCD中有两种队列:串行队列和并发队列。
• 并发队列:线程可以同时一起进行执行。实际上是CPU在多条线程之间快速的切换。(并发功能只有在异步(dispatch_async)函数下才有效)
• 串行队列:线程只能依次有序的执行。
• GCD总结:将任务(要在线程中执行的操作block)添加到队列(自己创建或使用全局并发队列),并且指定执行任务的方式(异步dispatch_async,同步dispatch_sync)
串行同步
- (void)GCD_serial_sync{
//1 。 串行同步 顺序执行 不开启新线程
dispatch_queue_t queue = dispatch_queue_create("serial_sync", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
NSLog(@"任务1 %@" , [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"任务2 %@" , [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"任务3 %@" , [NSThread currentThread]);
});
}
//输出结果 :任务1 、任务2、任务3
串行异步
- (void)GCD_serial_async{
//1 。 串行异步 顺序执行 开启新线程
dispatch_queue_t queue = dispatch_queue_create("serial_sync", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"任务1 %@" , [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"任务2 %@" , [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"任务3 %@" , [NSThread currentThread]);
});
}
//输出结果 :任务1 、任务2、任务3
并发 同步
- (void)GCD_concurrent_sync{
//1 。 并发同步 顺序执行 不开启新线程
dispatch_queue_t queue = dispatch_queue_create("serial_sync", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
NSLog(@"任务1 %@" , [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"任务2 %@" , [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"任务3 %@" , [NSThread currentThread]);
});
}
//输出结果 :任务1 、任务2、任务3
并发 异步
- (void)GCD_concurrent_async{
//1 。 并发异步 同时执行 开启新线程
dispatch_queue_t queue = dispatch_queue_create("serial_sync", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"任务1 %@" , [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"任务2 %@" , [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"任务3 %@" , [NSThread currentThread]);
});
}
//输出结果 :顺序不定
主队列
- (void)GCD_main_async{
// 异步可以执行
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"任务1");
dispatch_async(queue, ^{
NSLog(@"任务2 %@" , [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"任务3 %@" , [NSThread currentThread]);
});
//输出结果 : 任务1、任务2、任务3
// dispatch_sync(queue, ^{
// NSLog(@"任务3 %@" , [NSThread currentThread]);
// });
/**
如果添加上面你的同步代码,将会形成死锁
输出结果: 任务1
*/
}
线程间的通信
- (void)GCD_communication{
//将耗时操作放到子线程
//刷新ui放到主线程
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"在子线程中睡觉2s");
[NSThread sleepForTimeInterval:2];
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"回到主线程干事情");
});
});
}
GCD栅栏
- (void)GCD_barrier{
//1. 同步栅栏会阻塞线程 同步是阻塞当前线程
//2. 异步栅栏不会阻塞线程,阻塞的是队列列
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"任务1");
});
dispatch_async(queue, ^{
NSLog(@"任务2");
});
dispatch_barrier_sync(queue, ^{
NSLog(@"栅栏");
});
dispatch_async(queue, ^{
NSLog(@"任务3");
});
dispatch_async(queue, ^{
NSLog(@"任务4");
});
NSLog(@"任务5");
/**
栅栏同步 dispatch_barrier_sync : 任务1和任务2在栅栏前面,任务5在任务3和任务4 前面,中间是栅栏
任务1、任务2、栅栏、任务5、任务3、任务4
栅栏异步 dispatch_barrier_async :任务1、任务2在栅栏前面、任务3、任务4在栅栏后面,任务 5随时可能执行完成
任务1、任务5、任务2、栅栏、任务3、任务4
*/
}
GCD Group
-(void)GCD_group{
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"耗时任务1 %@",[NSThread currentThread]);
});
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"耗时任务2 %@",[NSThread currentThread]);
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"任务3");
});
}
//输出结果: 耗时任务1和耗时任务2没有顺序、任务3
GCD 延迟after 快速迭代appy
- (void)GCD_after_apply{
//延迟执行
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2*NSEC_PER_SEC)), dispatch_get_global_queue(0, 0), ^{
NSLog(@"延迟执行2s");
dispatch_apply(3, dispatch_get_global_queue(0, 0), ^(size_t index) {
//输出结果 : 0 1 2
NSLog(@"%zu",index);
});
});
}
GCD 计时器
//gcd 计时器
- (void)GCD_time{
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0) );
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 1 * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{
NSLog(@"定时器");
});
dispatch_resume(timer);
}
NSOperation 使用
- 创建任务:先将需要执行的操作封装到NSOperation对象中。
- 创建队列:创建NSOperationQueue。
- 将任务加入到队列中:将NSOperation对象添加到NSOperationQueue中。
- 调用start开启,谁先开启,谁先执行
创建方式
• initWithTarget 在主线程执行 没有开启新的队列
• blockOperationWithBlock 只有一个任务在主线程执行 。多个任务并发,任务1在主线程,其他在子线程,开启新线程
- (void)NSOperation_default{
//在主线程执行 没有开启新的队列
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationOperation) object:nil];
//只有一个任务在主线程执行 。多个任务并发,任务1在主线程,其他在子线程,开启新线程
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"block operation 任务1 %@",[NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
NSLog(@"block operation 任务2 %@",[NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
NSLog(@"block operation 任务3 %@",[NSThread currentThread]);
}];
[blockOperation start];
[operation start];
}
//输出结果:任务1、任务2和任务3顺序随意
NSOperationQueue
• NSOperation是需要配合队列NSOperationQueue来实现多线程的。
• 非主队列(其他队列)可以实现串行或并行。
• 队列NSOperationQueue有一个参数叫做最大并发数:maxConcurrentOperationCount。
• maxConcurrentOperationCount默认为-1,直接并发执行,所以加入到‘非队列’中的任务默认就是并发,开启多线程。
• 当maxConcurrentOperationCount为1时,则表示不开线程,也就是串行。
• 当maxConcurrentOperationCount大于1时,进行并发执行。
• 系统对最大并发数有一个限制,所以即使程序员把maxConcurrentOperationCount设置的很大,系统也会自动调整。所以把最大并发数设置的很大是没有意义的。
- (void)NSOperationQueue_concurrent{
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
#任务1
queue.maxConcurrentOperationCount = 5; //count = 1 串行 count>1并发 数字为几做多执行几个
#任务2
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"block 任务 %@",[NSThread currentThread]);
}];
NSInvocationOperation *inOPeration = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(invocationOperation) object:nil];
[queue addOperation:blockOperation];
[queue addOperation:inOPeration];
[blockOperation addDependency:inOPeration];//任务2 依赖于任务1执行
#任务3
[queue addOperationWithBlock:^{
NSLog(@"使用block添加任务 %@",[NSThread currentThread]);
}];
#任务4
[queue addBarrierBlock:^{
NSLog(@"barrier"); //使用栅栏,语gcd效果一样
}];
#任务5
[queue addOperationWithBlock:^{
NSLog(@"使用block添加任务%@",[NSThread currentThread]);
}];
#任务6
[queue addOperationWithBlock:^{
NSLog(@"使用block添加任务 %@",[NSThread currentThread]);
}];
}
//输出结果: 任务1在任务2之前执行 ,任务4是栅栏,所以要在任务1,任务2,任务3之后,任务5,任务6在任务4之后,关键顺序对了就可以,其他顺序随意
//任务3 -- 任务1 -- 任务2 -- 任务4 -- 任务5 --任务6