多线程
多线程
:一个进程中开辟多条线程,同时完成不同的任务,就是多线程。
创建方式:
pthread
:POSIX线程,简称pthread
,是线程的POSIX标准,该标准定义了创建和操纵线程的一整套API。是基于C语言的,可移植,OC中不太好管理,不建议。
- (void)pthreadsDoTask{
pthread_t thread = NULL;
NSString *params = @"Hello World";
int result = pthread_create(&thread, NULL, threadTask, (__bridge void *)(params));
result == 0?NSLog(@"creat thread success"):NSLog(@"creat thread failure");
pthread_detach(thread);
}
void *threadTask(void *params) {
NSLog(@"%@ - %@", [NSThread currentThread], (__bridge NSString *)(params));
return NULL;
}
2.NSThread
:轻量级的多线程开发,使用起来也并不复杂,但是需要自己管理线程生命周期,实在不是特别优雅
- (void)creatThread{
//在主线程中执行任务
[self performSelectorOnMainThread:@selector(MainThread:) withObject:nil waitUntilDone:nil];
//在其他线程总执行任务
//开始执行
[NSThread detachNewThreadWithBlock:^{
[self otherThreadAction:nil];
}];
[NSThread detachNewThreadSelector:@selector(otherThreadAction:) toTarget:self withObject:nil];
}
- (void)MainThread:(id)sender{
NSLog(@"主线程:%@",[NSThread currentThread]);
}
- (void)otherThreadAction:(id)sender{
NSLog(@"其他线程:%@",[NSThread currentThread]);
}
3.GCD
全名Grand Central Dispatch,是基于C语言的一套多线程开发API。GCD可以自动管理线程的生命周期以及任务的执行规则。
队列:
1.串行队列:所有任务会在一条线程中执行(
有可能是当前线程也有可能是新开辟的线程
),并且一个任务执行完毕后,才开始执行下一个任务
//串行队列
dispatch_queue_t serialQueue = dispatch_queue_create("MainQueue.com", DISPATCH_QUEUE_SERIAL);
//主队列
dispatch_get_main_queue()
并行队列:可以开启多条线程并行执行任务(
并不一定开启新的线程
),并且当一个任务放到指定线程开始执行时,在下一个任务就可以开始执行了。
//DISPATCH_TARGET_QUEUE_DEFAULT优先级
dispatch_get_global_queue(DISPATCH_TARGET_QUEUE_DEFAULT, 0);
concurrentQueue = dispatch_queue_create("ConcurrentQueue.com", DISPATCH_QUEUE_CONCURRENT);
执行任务的方式
同步执行
:在当前线程执行任务,不会开辟新的线程,必须等到Block函数执行完毕后,才会返回。dispatch_sync
异步执行
:可以在新的线程中执行任务,但不一定会开辟新的线程,dispatch函数会立即返回,然后在后台异步执行。dispatch_async
串行+同步
:不会开辟新的线程,在当前线程中执行。
串行+异步
:会开辟一个新的线程,在一个线程中执行任务。
并行+同步
:不会开辟新的线程,在当前线程中执行。
并行+异步
:会开辟新的线程,在不同的线程中同时完成任务。
dispatch_group
- (void)dispatchGroup{
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, concurrentQueue, ^{
NSLog(@"1-----%@",[NSThread currentThread]);
});
dispatch_group_async(group, concurrentQueue, ^{
NSLog(@"2-----%@",[NSThread currentThread]);
});
dispatch_group_async(group, concurrentQueue, ^{
NSLog(@"3-----%@",[NSThread currentThread]);
}) ;
dispatch_group_notify(group, concurrentQueue, ^{
NSLog(@"全部执行完成了");
});
}
dispatch_barrier 线程栅栏
线程栅栏可以阻塞某个queue中任务的执行知道queue中栅栏之前任务被执行完毕
- (void)dispatchBarrier{
dispatch_async(concurrentQueue, ^{
NSLog(@"栅栏 异步+并行+++1**********%@",[NSThread currentThread]);
});
dispatch_async(concurrentQueue, ^{
NSLog(@"栅栏 异步+并行+++2**********%@",[NSThread currentThread]);
});
dispatch_barrier_async(concurrentQueue, ^{
NSLog(@"栅栏");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"栅栏 +异步+并行+++3**********%@",[NSThread currentThread]);
});
dispatch_async(concurrentQueue, ^{
NSLog(@"栅栏 +异步+并行+++4**********%@",[NSThread currentThread]);
});
}
信号量
信号量类似于锁,简单来讲信号量为0则阻塞线程,大于0则不会阻塞,则我们通过改变信号量的值,来控制是否阻塞线程,从而达到线程同步
GCD中的信号量含有三个函数:
dispatch_semaphore_create(0)
创建一个semaphore信号量。
dispatch_semaphore_signal
发送一个信号让信号量+1
dispatch_semaphore_wait
如果信号量基数为0则阻塞等待、否则等待。
//创建信号量 ,设置值为
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, concurrentQueue, ^{
NSLog(@"信号量1-----%@",[NSThread currentThread]);
//信号量+1
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_semaphore_t semaphore1 = dispatch_semaphore_create(0);
dispatch_group_async(group, concurrentQueue, ^{
NSLog(@"信号量2-----%@",[NSThread currentThread]);
//信号量+1
dispatch_semaphore_signal(semaphore1);
});
dispatch_semaphore_wait(semaphore1, DISPATCH_TIME_FOREVER);
dispatch_semaphore_t semaphore2 = dispatch_semaphore_create(0);
dispatch_group_async(group, concurrentQueue, ^{
NSLog(@"信号量3-----%@",[NSThread currentThread]);
//信号量+1
dispatch_semaphore_signal(semaphore2);
}) ;
dispatch_semaphore_wait(semaphore2, DISPATCH_TIME_FOREVER);
dispatch_group_notify(group, concurrentQueue, ^{
NSLog(@"全部执行完成了");
});
NSOperation
是Apple对
GCD
面向对象的封装,它提供了关于任务的执行,取消以及随时获取任务的状态,添加任务依赖以及优先级等方法和属性,相对于GCD提供的方法来说,更直观,更方便,并且提供了更多的控制接口。
开启新的线程执行任务
- (void)operationQueue{
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
NSInvocationOperation *invocationOper = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(invocationSelector) object:nil];
//添加任务1
[queue addOperation:invocationOper];
NSBlockOperation *blockOper = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"NSBlockOperation——%@",[NSThread currentThread]);
}];
//添加任务2
[queue addOperation:blockOper];
[queue addOperationWithBlock:^{
NSLog(@"addOperationWithBlock——%@",[NSThread currentThread]);
}];
// 可以设置优先级
blockOper.queuePriority = NSOperationQueuePriorityLow;
}
队列插入操作后的执行顺序
首先,无论串行并行的条件下,队列内操作的执行依赖两条要素:
1.如果所插入的操作存在依赖关系,优先完成依赖操作
2.如果所插入的操作不存在依赖关系、队列并发数为1下采取先进先出的原则、反之直接开辟新的线程执行
iOS基础深入补完计划--GCD
iOS基础深入补完计划--多线程(面试题)汇总
关于iOS多线程,我说,你听,没准你就懂了!
网友评论