iOS多线程

2017-10-10  本文已影响0人  Alfred的记录本

NSOperation

-(void)loadImageWithMultiThread{
    /*创建一个调用操作
     object:调用方法参数
    */
    NSInvocationOperation *invocationOperation=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(loadImage) object:nil];
    //创建完NSInvocationOperation对象并不会调用,它由一个start方法启动操作,但是注意如果直接调用start方法,则此操作会在主线程中调用,一般不会这么操作,而是添加到NSOperationQueue中
//    [invocationOperation start];
    
    //创建操作队列
    NSOperationQueue *operationQueue=[[NSOperationQueue alloc]init];
    //注意添加到操作队后,队列会开启一个线程执行此操作
    [operationQueue addOperation:invocationOperation];
}
//直接使用操队列添加操作
        [operationQueue addOperationWithBlock:^{
            [self loadImage:[NSNumber numberWithInt:i]];
        }];

        //创建多线程操作
        NSBlockOperation *blockOperation=[NSBlockOperation blockOperationWithBlock:^{
            [self loadImage:[NSNumber numberWithInt:i]];
        }];
        //创建操作队列

        [operationQueue addOperation:blockOperation];
//更新UI界面,此处调用了主线程队列的方法(mainQueue是UI主线程)
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        [self updateImageWithData:data andIndex:i];
    }];

GCD

dispatch_queue_t queue = dispatch_queue_create("com.example.myQueue",  DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"block开始  queue:%@", [NSThread currentThread]);
        for(int i=0; i++ ; i<100) {
            
        }
        NSLog(@"block结束  queue:%@", [NSThread currentThread]);
    });
    NSLog(@"主线程  queue:%@", [NSThread currentThread]);

打印结果为:

block开始  queue:<NSThread: 0x60800006aa00>{number = 3, name = (null)}
主线程  queue:<NSThread: 0x604000067bc0>{number = 1, name = main}
block结束  queue:<NSThread: 0x60800006aa00>{number = 3, name = (null)}

dispatch_sycn函数意味着同步,也就是将block函数追加到queue中后,在block任务执行完之前,dispatch_sycn函数会一直等待。其实还是在主线程执行的。

dispatch_queue_t queue = dispatch_queue_create("com.example.myQueue",  DISPATCH_QUEUE_CONCURRENT);
    dispatch_sync(queue, ^{
        NSLog(@"block开始  queue:%@", [NSThread currentThread]);
        for(int i=0; i++ ; i<100) {}
        NSLog(@"block结束  queue:%@", [NSThread currentThread]);
    });
    NSLog(@"主线程  queue:%@", [NSThread currentThread]);

打印结果为:

block开始  queue:<NSThread: 0x6080000768c0>{number = 1, name = main}
block结束  queue:<NSThread: 0x6080000768c0>{number = 1, name = main}
主线程  queue:<NSThread: 0x6080000768c0>{number = 1, name = main}
- (void)serialQueueaSync {
    NSLog(@"serialQueueSync begin-------%@", [NSThread currentThread]);
    dispatch_queue_t queue = dispatch_queue_create("serialQueueSync", DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue, ^{
        for (int i=0; i<2; i++) {
            NSLog(@"1-------%@", [NSThread currentThread]);
        }});
    dispatch_async(queue, ^{
        for (int i=0; i<2; i++) {
            NSLog(@"2-------%@", [NSThread currentThread]);
        }});
    dispatch_async(queue, ^{
        for (int i=0; i<2; i++) {
            NSLog(@"3-------%@", [NSThread currentThread]);
        } });
    NSLog(@"serialQueueSync end-------%@", [NSThread currentThread]);
}

打印结果为:

serialQueueSync begin-------<NSThread: 0x60c0000628c0>{number = 1, name = main}
serialQueueSync end-------<NSThread: 0x60c0000628c0>{number = 1, name = main}
1-------<NSThread: 0x60c0002711c0>{number = 4, name = (null)}
1-------<NSThread: 0x60c0002711c0>{number = 4, name = (null)}
2-------<NSThread: 0x60c0002711c0>{number = 4, name = (null)}
2-------<NSThread: 0x60c0002711c0>{number = 4, name = (null)}
3-------<NSThread: 0x60c0002711c0>{number = 4, name = (null)}
3-------<NSThread: 0x60c0002711c0>{number = 4, name = (null)}
- (void)serialQueueSync {
    NSLog(@"serialQueueSync begin-------%@", [NSThread currentThread]);
    dispatch_queue_t queue = dispatch_queue_create("serialQueueSync", DISPATCH_QUEUE_SERIAL);
    dispatch_sync(queue, ^{
        for (int i=0; i<2; i++) {
            NSLog(@"1-------%@", [NSThread currentThread]);
        }});
    dispatch_sync(queue, ^{
        for (int i=0; i<2; i++) {
            NSLog(@"2-------%@", [NSThread currentThread]);
        } });
    dispatch_sync(queue, ^{
        for (int i=0; i<2; i++) {
            NSLog(@"3-------%@", [NSThread currentThread]);
        } });
    NSLog(@"serialQueueSync end-------%@", [NSThread currentThread]);
}

打印结果:

begin-------<NSThread: 0x608000060540>{number = 1, name = main}
1-------<NSThread: 0x608000060540>{number = 1, name = main}
1-------<NSThread: 0x608000060540>{number = 1, name = main}
2-------<NSThread: 0x608000060540>{number = 1, name = main}
2-------<NSThread: 0x608000060540>{number = 1, name = main}
3-------<NSThread: 0x608000060540>{number = 1, name = main}
3-------<NSThread: 0x608000060540>{number = 1, name = main}
 serialQueueSync end-------<NSThread: 0x608000060540>{number = 1, name = main}
    NSLog(@"hello world0");
    //因为是同步执行,所以
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"hello world1");
    });
    NSLog(@"hello world2");

同理,如下代码也会发生死锁,如下代码只会影响serialQueue内部发生死锁,不会阻塞主线程。

dispatch_queue_t serialQueue = dispatch_queue_create("com.example.gcd.serialQueue", NULL);
    NSLog(@"main begin");
    dispatch_async(serialQueue, ^{
        NSLog(@"外层begin");
        dispatch_sync(serialQueue, ^{
            NSLog(@"hello world");
        });
        NSLog(@"外层end");
        
    });
    NSLog(@"main end");

运行结果:

main begin
main end
外层begin
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, queue, ^{
        NSLog(@"block1 begin");
        for(int i=0; i<1000; i++){}
        NSLog(@"block1 end");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"block2 begin");
        for(int i=0; i<1000; i++){}
        NSLog(@"block1 end");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"block3 begin");
        for(int i=0; i<1000; i++){}
        NSLog(@"block3 end");
    });
    
    dispatch_group_notify(group, dispatch_get_main_queue()/*queue*/, ^{
        NSLog(@"done");
    });
    NSLog(@"testGroup END");

打印结果

block1 begin
testGroup END
block2 begin
block3 begin
block1 end
block3 end
block1 end
done

dispatch_group_notify(dispatch_group_t group, <#dispatch_queue_t queue#>, <#^(void)block#>)是等到之前与group联系过的block执行完后会把这个block提交到queue中。
无论向什么样的Dispatch Queue中追加任务,使用Dispatch Group都可以监视这些任务的结束。

NSMutableArray * array = @[@"1"].mutableCopy;
    dispatch_queue_t queue = dispatch_queue_create("com.example.gcd.ForBarrier", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"block1 = %@", array[0]);
        //读取处理block1
    });
    dispatch_async(queue, ^{
        NSLog(@"block2 = %@", array[0]);
        
        //读取处理block2
    });
    dispatch_async(queue, ^{
        sleep(2);
        NSLog(@"block3 = %@", array[0]);
        //读取处理block3
    });
    dispatch_barrier_async(queue, ^{
        NSLog(@"dispatch barrier begin");
        [array replaceObjectAtIndex:0 withObject:@"2"];
        NSLog(@"dispatch barrier end");
    });
    dispatch_async(queue, ^{
        NSLog(@"block4 = %@", array[0]);
    });

dispatch_barrier_async会等上面的block1, bolock2,block3 执行完成后,再执行自己的block,然后才是执行block4,运行结果:

block2 = 1
block1 = 1
block3 = 1
dispatch barrier begin
dispatch barrier end
block4 = 2

线程同步

除了 OSSpinLock 外,dispatch_semaphore 和 pthread_mutex 性能是最高的。有消息称,苹果在新系统中已经优化了 pthread_mutex 的性能,所以它看上去和 OSSpinLock 差距并没有那么大了。

参考文档

GCD常用方法总结
起底多线程同步锁(iOS)
NSRecursiveLock递归锁的使用
iOS多线程-各种线程锁的简单介绍

上一篇 下一篇

猜你喜欢

热点阅读