GCD 依次执行以及 NSOperationQueue 多线程

xiaoxiao2021-02-28  34

在iOS中,多线程使用较多的API是: NSOperationQueue 和 GCD 。其中 GCD 是基于 C 的底层的 API ,而 NSOperation 则是 GCD 实现的 OC的API,GCD使用方便,但代码较多,更致命的缺点如果是耗时操作,则无法取消任务,而NSOperationQueue则可以

 问题1 : 如果有N个任务,如何使N个任务依次执行?? NSOperationQueue 可以设置最大并发数,并进行任务依赖,GCD可以使用信号量来进行多线程通信。信号量控制主要分为三个步骤,设置信号初始值,降低信号量,增加信号量。

 方案: dispatch_semaphore_t 

 设置信号量初始值,该值可以理解为一次最多执行的任务数)(下图初始值为orig,信号量变化值为value)。

 dispatch_semaphore_t semaphore = dispatch_semaphore_create(3);

  dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);

  降低信号量,每次执行,初始值信号量就降低1,如果初始值降为0,则线程阻塞,该线程为等待线程(所 以此函数  避免在主线程中使用,避免阻塞主线程)(上图value值减小)

 dispatch_semaphore_signal(semaphore) 增加信号量,每次执行,初始值信号量就增加1,如果初始值不为0,则    唤醒一个等待线程,此函数和上面的降低信号量函数成对使用(上图value值增加1)

 测试代码:

 dispatch_semaphore_t semaphore =dispatch_semaphore_create(3);

dispatch_queue_t quene =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

    

    NSLog(@"================= 1");

    dispatch_async(quene, ^{

        dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);

        NSLog(@"task_1_1");

        sleep(2);

        dispatch_semaphore_signal(semaphore);

        NSLog(@"task_1_2");

    });

     NSLog(@"================= 2");

 

    dispatch_async(quene, ^{

        dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);

        NSLog(@"task_2_1");

        sleep(2);

        dispatch_semaphore_signal(semaphore);

        NSLog(@"task_2_2");

    });

     NSLog(@"================= 3");

    

    dispatch_async(quene, ^{

        dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);

        NSLog(@"task_3_1");

        sleep(1);

        dispatch_semaphore_signal(semaphore);

        NSLog(@"task_3_2");

    });

 举个例子: 假如一个屋子只能进去3个人(设置信号量初始值),现在屋子里没有人(没有任务执行),这时

    每次进入一个人,屋子能进去的人就减少一个(信号量减一),当屋子里三个人的时候(信号值为0),

 此时如果再来人,则需要等待(等待线程),如果从屋子里出来一个人,则就有一个人能够进入(信号

值增加一,唤醒一个等待线程执行任务),当屋子里的人全都出来时,则信号值为初始值3;

 NSOperation 子类使用

NSOperation 是一个抽象类,需要使用其子类NSInvocationOperation 和 NSBlockOperation

NSInvocationOperation *invocationO = [[NSInvocationOperationalloc] initWithTarget:selfselector:@selector(invocationOperationAction)object:nil];

[invocationO start];// 需要使用start方法进行任务执行,但线程是在执行的所在线程(在主线程就是主线程,而不会开辟线程

 NSBlockOperation *blockO = [NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"block 1 %@", [NSThreadcurrentThread]); // 主线程 block 1 <NSThread: 0x60c000073f40>{number = 1, name = main}

    }];

    [blockO addExecutionBlock:^{

        NSLog(@"block 2 %@", [NSThreadcurrentThread]); // 子线程 block 2 <NSThread: 0x608000267040>{number = 3, name = (null)}

    }];

    [blockO start]; // 执行

NSOperationQueue 使用

 //     创建主队列

        NSOperationQueue *mainOperation = [NSOperationQueue mainQueue];

        [mainOperation addOperationWithBlock:^{

            NSLog(@"是否主队列 %@", [NSThreadcurrentThread]); // 是否主队列 <NSThread: 0x60c000073f40>{number = 1, name = main}

        }];

 // 队列并发和串行

    NSOperationQueue *asyOperation = [[NSOperationQueuealloc] init]; // 非主队列

    asyOperation.maxConcurrentOperationCount =3; // 如果最大并发数大于1,则该队列为并发队列,为1时,该对列为串行队列。

 

   // 操作依赖

    NSBlockOperation *operationO_1 = [NSBlockOperationblockOperationWithBlock:^{

        NSLog(@"operationO_1");

    }];

    NSBlockOperation *operationO_2 = [NSBlockOperationblockOperationWithBlock:^{

        NSLog(@"operationO_2");

    }];

    NSBlockOperation *operationO_3 = [NSBlockOperationblockOperationWithBlock:^{

        NSLog(@"operationO_3");

    }];

    

    NSOperationQueue *operationQueue_3 = [[NSOperationQueuealloc] init];

    operationQueue_3.maxConcurrentOperationCount =2;

    [operationO_2 addDependency:operationO_1]; // 依赖  任务operationO_2 在 operationO_1 之后执行

    [operationO_3 addDependency:operationO_2];

    [operationQueue_3 addOperation:operationO_2];

    [operationQueue_3 addOperation:operationO_1];

    [operationQueue_3 addOperation:operationO_3];

 // 取消任务

  [operationO_1 cancel];// 取消单个任务 调用对象为NSOperation

[operationQueue_3 cancelAllOperation];// 取消所有任务 调用对象为NSOperationQueue

 

// 队列的暂停与恢复

[operationQ_2 setSuspended:YES]; // 队列暂停,挂起队列

 ------------------------------    如有错误,请进行纠正     ------------------------------------

转载请注明原文地址: https://www.6miu.com/read-2399994.html

最新回复(0)