dispatch_semphore 最多几个线程同时访问共享资源。
dispatch_sync 相当于 signal == 1 时的锁 而且 less error
所以政英那个tableview刷新 可优化成:
dispatch_sync(dispatch_get_mainqueue)
dispatch_async(serail_queue) 具备创建新线程的能力。 创建了一个串行队列,但是线程还是新的,比如在主线程调用这句话,就又创建了一个新的线程,只不过task是fifo一个接一个执行的。
The currently executing task runs on a distinct thread (which can vary from task to task)
dispatch_sync 没有创建新线程的能力
dispatch_sync(con_current) 虽然是异步队列,但还是再当前线程,所以还是顺序执行。
dispatch_async_group
dispatch_group_async(dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block);
把block 添加到队列 然后跟group相关联 group里面blocks都执行完时,
dispatch_group_notify 不阻塞当前线程 只是保证 添加到group的blocks都完成后 执行 notify里面的block
dispatch_group_wait 阻塞当前线程 (调用这个方法时的线程,不是 group里面添加的线程) 所以最好不要在 serail queue调用这个方法 (serail queue == main queue时, 线程为主线程, 所以直接卡主, 不为 main queue时, 阻塞调用wait方法时的线程,所以最好是concurrent queue 把线程切到一个新的)
dispatch_async(syqueue, ^{
----> syqueue 不管是串行还是并行 都是创建了一个新的thread 不是main thread.
NSLog(@"group_before_1, current thread = %@", [NSThread currentThread]);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, syqueue, ^{
-----> 当 syqueue 为 concurrent queue 时, 应该是又切了一次,所以重新创建了一个跟wait是不同的thread, 所以block可以执行
-----> 当 syqueue 为 serail queue 时, 因为最开始是在syqueue里,因为是serail, 这里应该没切到别的线程!! 所以在wait那里就卡住了, 这里block没执行。
NSLog(@"group_2, current thread = %@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:1];
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
---> wait 阻塞当前线程, 需要跟group绑定的blocks都执行完
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"group_3");
});
---> notify 不阻塞当前线程, 直接往下走
NSLog(@"group_after_4, current thread = %@", [NSThread currentThread]);
});
dispatch_async(syqueue, 只要是 async 就可以切到新的线程 不管 queue是串行还是并行。
YYKit线程池:
第一次创建时, 根据优先级,创建了5个不同的pool (主要为context结构体)
queue 主要根据 qos 串行并行 这两个参数创建
个数根据当前CPU个数创建
typedef struct {
const char *name;
void **queues;
uint32_t queueCount;
int32_t counter;
} YYDispatchContext;
static YYDispatchContext *YYDispatchContextCreate(const char *name,
uint32_t queueCount,
NSQualityOfService qos) {
YYDispatchContext *context = calloc(1, sizeof(YYDispatchContext));
if (!context) return NULL;
context->queues = calloc(queueCount, sizeof(void *));
if (!context->queues) {
free(context);
return NULL;
}
if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) {
dispatch_qos_class_t qosClass = NSQualityOfServiceToQOSClass(qos);
for (NSUInteger i = 0; i < queueCount; i++) {
dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, qosClass, 0);
dispatch_queue_t queue = dispatch_queue_create(name, attr);
context->queues[i] = (__bridge_retained void *)(queue);
}
int count = (int)[NSProcessInfo processInfo].activeProcessorCount;
复用时, 根据counter + 1 % count 来取
static dispatch_queue_t YYDispatchContextGetQueue(YYDispatchContext *context) {
uint32_t counter = (uint32_t)OSAtomicIncrement32(&context->counter);
void *queue = context->queues[counter % context->queueCount];
return (__bridge dispatch_queue_t)(queue);
}