ios 多线程

转自:http://www.maxiaoguo.com/clothes/254.html

多线程包括:GCD  NSOperation   NSOperation是在GCD语言的基础上开发的,GCD类C语言, NSOperation OC语法

GCD:

名词解释 

并行
 dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_CONCURRENT);
 串行
 dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_SERIAL);
全局队列
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
 异步任务
 dispatch_async(q, ^{
        NSLog(@"异步任务 %@1111111", [NSThread currentThread]);
  });
同步任务
dispatch_sync(q, ^{
    NSLog(@"同步任务 %@1111111", [NSThread currentThread]);
 });

dispatch_queue_t q = dispatch_queue_create("cn.itcast.demoqueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(q, ^{
    NSLog(@"并行同步 %@", [NSThread currentThread]);
});

主队列:

dispatch_queue_t q = dispatch_get_main_queue();

    dispatch_async(q, ^{
        NSLog(@"主队列异步 %@", [NSThread currentThread]);
    });
容易发成死锁情况:

串行队列开启同步任务后嵌套同步任务造成死锁

 串行队列开启异步任务后嵌套同步任务造成死锁

主队列不能放同步任务


NSOperation 中的 NSBlockOperation 

用法:

n定义操作并添加到队列
self.myQueue = [[NSOperationQueue alloc] init];
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
    [self operationAction:@"BlockOperation"];
}];
n将操作添加到队列
[self.myQueue addOperation:op];
这样的 NSBlockOperation是默认的异步的并行队列
设定dependency可以改成串行并列
 // 设定执行顺序, Dependency依赖,可能会开多个,但不会太多
    // 依赖关系是可以跨队列的!
    [op2 addDependency:op1];
    [op3 addDependency:op2];
    [op4 addDependency:op3];
    // GCD是串行队列,异步任务,只会开一个线程

NSOperation 中的 NSInvocationOperation

  // 需要定义一个方法,能够接收一个参数
    // 是用起来不够灵活
    NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demoOp:) object:@"hello op"];
//    [self.myQueue addOperation:op];
    [[NSOperationQueue mainQueue] addOperation:op];

线程的资源抢夺:

解决方法: 加@synchronized


生成单例DemoObj的单例

+ (id)allocWithZone:(struct _NSZone *)zone
{
    static DemoObj *instance;
    
    // dispatch_once是线程安全的,onceToken默认为0
    static dispatch_once_t onceToken;
    // dispatch_once宏可以保证块代码中的指令只被执行一次
    dispatch_once(&onceToken, ^{
        // 在多线程环境下,永远只会被执行一次,instance只会被实例化一次
        instance = [super allocWithZone:zone];
    });
    
    return instance;
}
错误写法,原因:当多个线程同时执行的时候会生成多个instance

+ (instancetype)sharedDemoObj
{
    // 如果有两个线程同时实例化,很有可能创建出两个实例来
//    if (!instance) {
//        // thread 1 0x0000A
//        // thread 2 0x0000B
//        instance = [[self alloc] init];
//    }
//    // 第一个线程返回的指针已经被修改!
//    return instance;
    return [[self alloc] init];
}

NSThread

NSThread的创建主要有两种直接方式:

[NSThread detachNewThreadSelector:@selector(myThreadMainMethod:) toTarget:self withObject:nil];
和
NSThread* myThread = [[NSThread alloc] initWithTarget:self
                                        selector:@selector(myThreadMainMethod:)
                                        object:nil];
[myThread start];

这两种方式的区别是:前一种一调用就会立即创建一个线程来做事情;而后一种虽然你 alloc 了也 init了,但是要直到我们手动调用 start 启动线程时才会真正去创建线程。这种延迟实现思想在很多跟资源相关的地方都有用到。后一种方式我们还可以在启动线程之前,对线程进行配置,比如设置 stack 大小,线程优先级。

还有一种间接的方式,更加方便,我们甚至不需要显式编写 NSThread 相关代码。那就是利用 NSObject 的类方法 performSelectorInBackground:withObject: 来创建一个线程:
[myObj performSelectorInBackground:@selector(myThreadMainMethod) withObject:nil];
其效果与 NSThread 的 detachNewThreadSelector:toTarget:withObject: 是一样的。





你可能感兴趣的:(ios 多线程)