iOS:线程终止以及GCD中dispatch_semaphore,dispatch_barrier_async,dispatch_group使用说明

本文介绍GCD中线程并发控制的方法,包括通过dispatch_semaphore_t和NSOperationQueue设置最大并发数,以及如何使用dispatch_barrier_async进行任务隔离。同时探讨了dispatch_group的功能及其在并行任务中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1,今天更新一下关于线程的一些小知识。

前提:dispatch_get_main_queue()本质是串行队列,dispatch_get_global_queue(0, 0)本质是并行队列

串行队列:DISPATCH_QUEUE_SERIAL 最多开辟一个线程

并行队列:DISPATCH_QUEUE_CONCURRENT 可开启n的线程,n>=0

主队列执行async任务时,会在主线程执行,因为主线程就是主队列开辟的线程。

并行队列执行sync任务时,不会开辟新线程,会在当前线程中执行。

一、设置线程并发量

线程并发量:如果需要加载1000张图片,如果开启1000个子线程,那么CPU可能就忙不过来了,这时我们可以设置最大并发量来更加合理的利用资源。同时只允许10个线程下载,每个任务完成后,让改线程执行下一个任务

两种实现:

1、GCD:通过dispatch_semaphore实现

static dispatch_semaphore_t semaphoreLock;
void testDispatch_semaphore () {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        semaphoreLock = dispatch_semaphore_create(5);
    });
    dispatch_semaphore_wait(semaphoreLock, DISPATCH_TIME_FOREVER);
    //code...
    dispatch_semaphore_signal(semaphoreLock);
}

其中dispatch_semaphore_create(5)中的5就是最大并发数。执行到wait时,会变成4,只到变成0,在有线程来到wait就会阻塞到这里了,要等要某个线程dispatch_semaphore_signal()时,信号就会+1,然后等待的线程就是执行,始终保持着最大线程数是5

2、NSOperationQueue实现

NSOperationQueue有个属性maxConcurrentOperationCount设置最大并发数,和dispatch_semaphore_create一样

NSOperationQueue *queue =[[NSOperationQueue alloc] init];
[queue addOperation:...];
[queue addOperation:...];
queue.maxConcurrentOperationCount = 5;

注意:线程的cancel操作都不能取消正在执行的任务,只能取消在队列中排队的任务。要想取消正在执行的任务,只能通过添加信号量的方式,强制让任务提前return

//线程已经停止,需要跳出循环
if ([_invo isCancelled]) {
    return; // 跳出循环。
}

//或者
if (_stopFlag){
    return;
}

二、GCD常用函数

1、dispatch_barrier_async

dispatch_barrier_async:栅栏化,在栅栏任务前面的任务可以异步执行,等到前面的异步任务执行完了,才会执行栅栏中的任务,栅栏后面的任务也可以异步执行。

dispatch_barrier_async要搭配并发队列才能达到隔离效果,如果使用的是串行队列,那么就会一个线程一个线程执行,没有隔离效果

void testGCD () {
    dispatch_queue_t queue = dispatch_queue_create("ob", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"start -- %@",[NSThread currentThread]);
        sleep(2);
        NSLog(@"end -- %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"start -- %@",[NSThread currentThread]);
        sleep(2);
        NSLog(@"end -- %@",[NSThread currentThread]);
    });
    dispatch_barrier_async(queue, ^{
        NSLog(@"start -- %@",[NSThread currentThread]);
        sleep(4);
        NSLog(@"end -- %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"start -- %@",[NSThread currentThread]);
        sleep(2);
        NSLog(@"end -- %@",[NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"start -- %@",[NSThread currentThread]);
        sleep(2);
        NSLog(@"end -- %@",[NSThread currentThread]);
    });
}

打印如下:
 

2020-07-09 14:01:27.801176+0800 start -- <NSThread: 0x1005156d0>{number = 3, name = (null)}
2020-07-09 14:01:27.801179+0800 start -- <NSThread: 0x10063a510>{number = 2, name = (null)}
2020-07-09 14:01:29.806139+0800 end -- <NSThread: 0x1005156d0>{number = 3, name = (null)}
2020-07-09 14:01:29.806139+0800 end -- <NSThread: 0x10063a510>{number = 2, name = (null)}
2020-07-09 14:01:29.806349+0800 start -- <NSThread: 0x1005156d0>{number = 3, name = (null)}
2020-07-09 14:01:33.811750+0800 end -- <NSThread: 0x1005156d0>{number = 3, name = (null)}
2020-07-09 14:01:33.811914+0800 start -- <NSThread: 0x1005156d0>{number = 3, name = (null)}
2020-07-09 14:01:33.811915+0800 start -- <NSThread: 0x10063a510>{number = 2, name = (null)}
2020-07-09 14:01:35.816482+0800 end -- <NSThread: 0x10063a510>{number = 2, name = (null)}
2020-07-09 14:01:35.816497+0800 end -- <NSThread: 0x1005156d0>{number = 3, name = (null)}

二、dispatch_group

  1. dispatch_group_enter :通知 group,下个任务要放入 group 中执行了
  2. dispatch_group_leave: 通知 group,任务成功完成,要移除,与 enter成对出现
  3. dispatch_group_wait: 在任务组完成时调用,或者任务组超时是调用(完成指的是enter和leave次数一样多)
  4. dispatch_group_notify: 只要任务全部完成了,就会在最后调用

其中,dispatch_group_notify安全起见要使用dispatch_group_wait,等到前面的执行完了才行,同样的只能适应在并行队列。串行队列按顺序执行,并且一个线程执行所有任务。即使使用async也不会创建多线程。

void testGroup () {
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_queue_create("ob", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_notify(group, queue, ^{
        dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
        NSLog(@"notify -- %@",[NSThread currentThread]);
    });
    
//    dispatch_group_enter(group);
    dispatch_group_async(group, queue, ^{
        NSLog(@"start -- %@",[NSThread currentThread]);
        sleep(5);
        NSLog(@"end -- %@",[NSThread currentThread]);
//        dispatch_group_leave(group);
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"start -- %@",[NSThread currentThread]);
        sleep(1);
        NSLog(@"end -- %@",[NSThread currentThread]);
    });
  
    dispatch_group_async(group, queue, ^{
        NSLog(@"start -- %@",[NSThread currentThread]);
        sleep(3);
        NSLog(@"end -- %@",[NSThread currentThread]);
    });
  
}


后期更新中。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值