iOS 多线程如何取消任务及控制最大并发量

2,172 阅读2分钟

多线程

主要有三种:NSThread、NSoperationQueue、GCD

NSThread

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(testThread:) object:@"我是参数"];
    // 当使用初始化方法出来的主线程需要start启动
    [thread start];
    // 可以为开辟的子线程起名字
    thread.name = @"NSThread线程";
    // 调整Thread的权限 线程权限的范围值为0 ~ 1 。越大权限越高,先执行的概率就会越高,由于是概率,所以并不能很准确的的实现我们想要的执行顺序,默认值是0.5
    thread.threadPriority = 1;
    // 取消当前已经启动的线程
    [thread cancel];
    // 通过遍历构造器开辟子线程
    [NSThread detachNewThreadSelector:@selector(testThread:) toTarget:self withObject:@"构造器方式"];

GCD

取消任务

- (void)gcdBlockCancel{
    dispatch_queue_t queue = dispatch_queue_create("com.gcdtest.www", DISPATCH_QUEUE_CONCURRENT);
    dispatch_block_t block1 = dispatch_block_create(0, ^{
        sleep(3);
        NSLog(@"block1 %@",[NSThread currentThread]);
    });
    dispatch_block_t block2 = dispatch_block_create(0, ^{
        NSLog(@"block2 %@",[NSThread currentThread]);
    });
    dispatch_block_t block3 = dispatch_block_create(0, ^{
        NSLog(@"block3 %@",[NSThread currentThread]);
    });
    dispatch_async(queue, block1);
    dispatch_async(queue, block2);
    dispatch_async(queue, block3);
    dispatch_block_cancel(block3);
}

控制最大并发量

  • 信号量是一个整型值,有初始计数值;可以接收通知信号和等待信号。当信号量收到通知信号时,计数+1;当信号量收到等待信号时,计数-1;如果信号量为0,线程会被阻塞,直到信号量大于0,才会继续下去。

  • 使用信号量机制可以实现线程的同步,也可以控制最大并发数。以下是如何控制最大并发数的代码

dispatch_queue_t concurrentQueue =dispatch_queue_create("plz", DISPATCH_QUEUE_CONCURRENT);
    dispatch_queue_t seriaQueue = dispatch_queue_create("s", DISPATCH_QUEUE_SERIAL);
    dispatch_semaphore_t semaphore =dispatch_semaphore_create(4);
    
    for (int i =0; i<10; i++) {
        dispatch_async(seriaQueue, ^{
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            dispatch_async(concurrentQueue, ^{
                NSLog(@"thread-info:%@开始执行任务%d",[NSThread currentThread],(int)i);
                sleep(1);
                NSLog(@"thread-info:%@结束执行任务%d",[NSThread currentThread],(int)i);
                dispatch_semaphore_signal(semaphore);
            });
        });
    }
    NSLog(@"主线程...!");

NSOperationQueue

控制最大并发量

NSOperationQueue中,已经考虑到了最大并发数的问题,并提供了maxConcurrentOperationCount属性设置最大并发数(该属性需要在任务添加到队列中之前进行设置)。maxConcurrentOperationCount默认值是-1;如果值设为0,那么不会执行任何任务;如果值设为1,那么该队列是串行的;如果大于1,那么是并行的。

NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    queue.maxConcurrentOperationCount = 3;
    for (int i =0; i<10; i++) {
        [queue addOperationWithBlock:^{
            NSLog(@"thread-info:%@开始执行任务%d",[NSThread currentThread],(int)i);
            sleep(1);
            NSLog(@"thread-info:%@结束执行任务%d",[NSThread currentThread],(int)i);
        }];
    }

回到主线程

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
                    NSLog(@"***%@", [NSThread currentThread]);
                }];

取消任务

- (void)addCustomeOperationQueue {
    NSLog(@"创建添加任务%@",[NSThread currentThread]);
    NSOperationQueue *customQueue = [[NSOperationQueue alloc]init];
    customQueue.maxConcurrentOperationCount = 5;
    
    NSInvocationOperation *op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(task:) object:@"1"];
     [customQueue addOperation:op1];
  
    NSInvocationOperation *op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(task:) object:@"2"];

    NSInvocationOperation *op3 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(task:) object:@"3"];
    
    NSInvocationOperation *op4 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(task:) object:@"4"];
  
    //这个方法只能取消还未开始执行的操作,如果操作已经开始执行,那么该方法依然取消不了。
    [customQueue cancelAllOperations];
    //取消某个操作,可以直接调用操作的取消方法cancel。
    [op1 cancel];
    [customQueue addOperation:op2];
    [customQueue addOperation:op3];
    [customQueue addOperation:op4];
}

待更新。。。