线程:
时间:线程在时间上可以分为“串行” 和“并发”两种方式,同步就是让我们的线程同时执行,异步线程不同时执行。强调时间性。
关系:线程在线程之间关系上可以分为“顺序执行”和“并行执行”,强调的是线程之间的关系。
任务:同步(Sync)和 异步(Async)(任务:就是执行操作,就是代码的运行)
同步(Sync)
- 同步添加任务到指定的队列中,在添加的任务执行结束之前,会一直等待,直到队列里面的任务完成之后再执行
- 只能在当前线程中执行任务,不具备开启新线程的能力
异步(Async)
- 异步添加任务到指定的队列中,它不会做任何等待,可以继续执行任务
- 可以在新的线程中执行任务,具备开启新线程的能力
队列 :串行和并行。
串行和并行
- 相同: 串行队列和并发队列都符合先进先出的原则。
- 区别: 执行的顺序不同,以及开启的线程数不同
四种组合情况(GCD为例)
- (void)viewDidLoad {
[super viewDidLoad];
//1.获取并行队列,异步追加任务
//[self concurrentAndAsync];
//2.获取并行队列,同步追加任务
//[self concurrentAndSync];
//3.创建串行队列,异步追加任务
//[self serialAndAsync];
//4.创建串行队列,同步追加任务
//[self serialAndSync];
//5.向主队列中同步追加任务引起死锁
[self addSyncTaskToMainQueue];
[self mainQueuePrintTask];
}
1.获取并行队列,异步追加任务
- (void)concurrentAndAsync {
//(1)获取全局队列
dispatch_queue_t queue = dispatch_get_global_queue(
DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//(2)开启多线程1:添加任务1
dispatch_async(queue, ^{
for (int i = 0; i < 20;i++) {
NSLog(@"多线程1:%i", i);
}
});
//(3)开启多线程2:添加任务2
dispatch_async(queue, ^{
for (int i = 0; i < 20;i++) {
NSLog(@"多线程2:%i", i);
}
});
//睡眠
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(2.0 * NSEC_PER_SEC)), queue, ^{
NSLog(@"-------------等待2秒");
// 2秒后异步执行这里的代码...
[self postNoti];
NSLog(@"-------------time");
});
}
//打印结果: 主线程和多线程 之间没有任何先后顺序 同时执行
//打印结果: 主线程1和多线程2 之间也没有任何先后顺序 并发执行
2.获取并行队列,同步追加任务
- (void)concurrentAndSync {
//(1)获取全局队列
dispatch_queue_t queue = dispatch_get_global_queue(
DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//(2)添加任务1
dispatch_sync(queue, ^{
for (int i = 0; i < 20;i++) {
NSLog(@"任务1:%i", i);
}
});
//(3)添加任务2
dispatch_sync(queue, ^{
for (int i = 0; i < 20;i++) {
NSLog(@"任务2:%i", i);
}
});
}
//打印结果: 多线程在前 优先执行,多线程完成之后,主线程才执行
//打印结果: 多线程之中任务1在前 先执行 任务1完成之后,才执行任务2
3.创建串行队列,异步追加任务
- (void)serialAndAsync {
//(1)创建串行队列
dispatch_queue_t queue = dispatch_queue_create("iOS", DISPATCH_QUEUE_SERIAL);
//(2)添加任务1
dispatch_async(queue, ^{
for (int i = 0; i < 20;i++) {
NSLog(@"串行队列中执行任务1:%i", i);
}
});
//(3)添加任务2
dispatch_async(queue, ^{
for (int i = 0; i < 20;i++) {
NSLog(@"串行队列中执行任务2:%i", i);
}
});
}
//打印结果: 主线程和多线程 之间没有任何先后顺序 同时执行
//打印结果: 多线程之中任务1在前 先执行 任务1完成之后,才执行任务2
4.创建串行队列,同步追加任务
- (void)serialAndSync {
//(1)创建串行队列
dispatch_queue_t queue = dispatch_queue_create("iOS", DISPATCH_QUEUE_SERIAL);
//(2)添加任务1
dispatch_sync(queue, ^{
for (int i = 0; i < 20;i++) {
NSLog(@"串行队列中执行任务1:%i", i);
}
});
//(3)添加任务2
dispatch_sync(queue, ^{
for (int i = 0; i < 20;i++) {
NSLog(@"串行队列中执行任务2:%i", i);
}
});
}
//打印结果: 多线程在前 优先执行,多线程完成之后,主线程才执行
//打印结果: 多线程之中任务1在前 先执行 任务1完成之后,才执行任务2
5.向主队列中同步追加任务引起死锁
- (void)serialAndSync {
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(mainQueue, ^{
//NSLog(@"主队列中添加此任务");
for (int i =0; i < 50; i++) {
NSLog(@"%i", i);
}
});
}
//打印结果: 只有mainQueuePrintTask方法的打印,没有本方法的打印
主线程方法
- (void)postNoti{
NSLog(@"睡眠2秒");
}
- (void)mainQueuePrintTask {
for (int i = 0; i < 50000;i++) {
NSLog(@"主线程:%i", i);
}
}
同步执行 + 串行队列:我们把任务分配一个个线程,每个线程的任务都在主线程中执行。
异步执行 + 串行队列:队列中的任务顺序执行:在子线程中执行,主线程继续,不会等待子线程执行完毕。
同步执行 + 并发队列:(一般不用):队列中任务顺序执行,在主线程中执行(并行)
异步执行 + 并发队列:队列中的任务同时执行;在子线程中执行;主线程继续执行,不会等待子线程执行完毕。
NSThread的使用
1.优点:NSThread比其他两种多线程方案较轻量级,更直观地控制线程对象
2.缺点:需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销
- (void)viewDidLoad {
[super viewDidLoad];
//1.创建线程对象
NSThread *thread = [[NSThread alloc] initWithTarget:self
selector:@selector(thread) object:nil];
thread.name = @"thread-2";
// 设置线程的优先级(0.0 - 1.0,1.0最高级)
thread.threadPriority = 1;
//开启一个多线程
[thread start];
//2.创建一个线程对象,并且直接开启此线程,但无法获取线程对象。
//[NSThread detachNewThreadSelector:@selector(thread)
toTarget:self withObject:nil];
//3.创建一个线程对象,并且启动此线程,调用当前self对象的方法。(隐式创建线程的方法)
//[self performSelectorInBackground:@selector(thread) withObject:nil];
//[self thread];
for (int i = 0; i < 20; i++) {
NSLog(@"主线程:%i",i);
}
}
多线程的入口方法
- (void)thread {
//获取当前方法的线程对象
NSThread *thread = [NSThread currentThread];
NSLog(@"thread-2:%@", thread);
//获取主线程
//NSThread *main = [NSThread mainThread];
//多线程分配堆栈大小为512k
NSLog(@"thread-2:stackSize:%li", [thread stackSize]);
for (int i = 0; i < 50; i++) {
if (i == 10) {
NSLog(@"thread sleep");
//使当前线程睡眠
[NSThread sleepForTimeInterval:2];
}
if (i == 20) {
NSLog(@"thread end");
//线程退出
[NSThread exit];
}
NSLog(@"thread:%i",i);
}
//判断当前线程是否为主线程
if (![NSThread isMainThread]) {
NSLog(@"当前线程不是主线程");
}
}
NSOperationQueue使用
- (void)viewDidLoad {
[super viewDidLoad];
//1.创建一个线程队列(线程池)
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//2.创建线程 //NSOperation->NSInvocationOperation
NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(thread1:) object:@"operation-1"];
NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(thread2:)object:@"operation-2"];
HWOperation *op3 = [[HWOperation alloc] initTarget:self
selector:@selector(thread3)];
//设置queue的并发数
//queue.maxConcurrentOperationCount = 1;
op2.queuePriority = NSOperationQueuePriorityVeryHigh;
//[queue setSuspended:YES];
//3.把线程对象加入到线程队列中
[queue addOperation:op1];
[queue addOperation:op2];
[queue addOperation:op3];
//[queue setSuspended:NO];
//[queue addOperationWithBlock:^{
// for (int i = 0; i < 20; i++) {
// NSLog(@"block:%i", i);
// }
//}];
for (int i = 0; i < 10; i++) {
NSLog(@"主线程:%i",i);
}
}
线程方法
//线程thread1入口方法
- (void)thread1:(NSString *)name {
for (int i = 0; i < 20; i++) {
NSLog(@"多线程%@:%i", name, i);
}
}
//线程thread2入口方法
- (void)thread2:(NSString *)name {
for (int i = 0; i < 20; i++) {
NSLog(@"多线程%@:%i", name, i);
}
}
//自定义线程类:thread3的入口方法
- (void)thread3 {
for (int i = 0; i < 20; i++) {
NSLog(@"HWOPeration线程:%i", i);
}
}
只是简单使用,多有不足,有时间再补充吧