ios thread

概念:

单线程:程序是按从上到下顺序执行的,会有时间延迟

多线程:可以同时进行

NSLog(@" "); //会很耗时的,调试完应该关掉,也可用断点+po来输出对象```

#####1. 单线程:
修改界面操作不是像代码一样马上就改,为了节省效率,而是首先是记录一下,代码执行完之后统一渲染出来,只要有耗时的代码就会使得界面加载延迟(界面假死(阻塞),用户体验灰常不好)

-   **解决:**
>1)、**不能在主线程里面做耗时操作**,放在子线程中,主线程用来接受用户交互,界面渲染等操作,让它保持畅通。

  >2)、**不能把修改页面的代码放到子线程**(因为如果修改页面的代码放到子线程,修改之后还有别的事情要做的话,界面也会等别的事情处理完才展示,会出现界面响应不及时的情况)

-   **耗时操作:**

 >    1、所有和网络相关的
     2、加载大文件
     3、大量运算
     4、睡眠代码[NSThread sleepForTimeInterval:2];

----

#####2. 开启线程有三种:
>1)、**NSThread**:
2)、**GCD:** 中央任务分发,由c语言实现,支持更底层(block里面是子线程),有线程队列,有串行与并行
3)、**NSOperation:** OC的,有线程队列,没有并,串行的概念,也可以实现并行,可以实现线程之间的关系(依赖关系,可以控制先后执行,其他不可以)


######1)、NSThread


NSLog(@"%@"[NSThread currentThread]); //输出线程名

-   开启子线程

//1、开启一个子线程去立即执行addViews方法,代码执行完线程自动开始执行
[NSThread detachNewThreadSelector:@selector(addViews) toTarget:self withObject:nil]; //nil什么也没有传过去

//2、NSThread 第二种写法:
NSThread *t1 = [[NSThread alloc] initWIthTarget:self selector"@selecteor(newAction:) object:nil];
t1.name = @"2号线程"; //可以給线程加名字
//开始执行
[t1 start];
```
  • 回到主线程调用修改页面的方法
  - (void)addViews{
    for (int i=0; i<5; i++) {
        //    for (int i=0; i<10000; i++) {
        //        NSLog(@"%d",i);
        //    }

        [NSThread sleepForTimeInterval:1];  //耗时操作 睡眠1秒

        //回到主线程调用修改页面的方法     waitUntilDone是否等待主线程完成之后子线程再继续执行
         //一般是    NO, Yes2边(主,子线程)执行结果有关联的时候用
        [self performSelectorOnMainThread:@selector(updateUI:) withObject:@(i) waitUntilDone:NO]; //传个执行次数的参数过去
    }
}

// 主线程调用方法
 - (void)updateUI:(NSNumber *)number{
    int i = [number intValue];

     //修改页面的代码
    UIView *v = [[UIView alloc]initWithFrame:CGRectMake(100, i*110, 100, 100)];
    v.backgroundColor = [UIColor redColor];
    [self.view addSubview:v];
}```

----

######2)、 GCD:不需要添加多余的方法

//创建 串行队列
dispatch_queue_t myQueue = dispatch_queue_create("myQ", NULL);

//在队列中开启线程并执行
dispatch_async(myQueue, ^{
for (int i=0; i<5; i++) {
NSLog(@"线程1-%d",i);
}
//在队列中开启线程并执行
});

dispatch_async(myQueue, ^{
    for (int i=0; i<5; i++) {
        NSLog(@"线程2-%d",i);
    }
});

// 得到 并行队列
dispatch_queue_t myQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(myQueue, ^{
for (int i=0; i<5; i++) {
NSLog(@"线程1-%d",i);
}
//在队列中开启线程并执行
});

dispatch_async(myQueue, ^{
    for (int i=0; i<5; i++) {
        NSLog(@"线程2-%d",i);
    }
});

```

3、NSOperation: 不需要添加多余的方法,用block
//默认并行:
    //创建线程队列
    NSOperationQueue *myQueue = [NSOperationQueue new];

    //创建线程1
    NSOperation *op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(newThreadAction) object:nil];

    //创建线程2
    NSOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
    //不需要添加方法
     for (int i=0; i<3; i++) {
            NSLog(@"线程二   %d",i);
        }
    }];

   //把线程添加到队列中  同时线程会自动开始执行
   [myQueue addOperation:op1];
   [myQueue addOperation:op2];

//线程1 的调用方法
 - (void)newThreadAction {
    for (int i=0; i<3; i++) {
        NSLog(@"线程一   %d",i);
    }
}
//实现串行:
  //添加约束
    //1、设置线程并行的数量(1,为一个一个执行实现串行效果)
    [myQueue setMaxConcurrentOperationCount:1];

    //2、设置线程之间的关系 让op2 依赖于 op1,先执行op1
    [op1 addDependency:op2];

3. 多线程安全

当多条线程去同时修改一份数据的时候,有可能会出现安全问题(买票等等)
解决:通过同步代码块

方法1: @synchronized(self) {}
- (void)viewDidLoad {
    [super viewDidLoad];

    self.totalCount = 100;

    NSThread *t1 = [[NSThread alloc]initWithTarget:self selector:@selector(sellAction) object:nil];
    t1.name = @"1号窗口";
    [t1 start];

    NSThread *t2 = [[NSThread alloc]initWithTarget:self selector:@selector(sellAction) object:nil];
    t2.name = @"2号窗口";
    [t2 start];
}

- (void)sellAction{
    while (YES) {
        //通过线程同步 让某段核心代码 只能有一个线程执行(加锁)
        @synchronized(self) {
            NSString *name = [NSThread currentThread].name;
            NSLog(@"%@开始卖%d号票",name,self.selledCount+1);
            [NSThread sleepForTimeInterval:.5];
            self.selledCount++;
            NSLog(@"%@卖掉了%d号票 还剩%d张",name,self.selledCount,self.totalCount-self.selledCount);
        }
    }
}```


######方法2:NSLock

//声明属性
@property(nonatomic, strong)NSLock *myLock;

- (void)sellAction{
while (YES) {
    //通过线程同步 让某段核心代码 只能有一个线程执行(加锁)

// @synchronized(self) {
[self.myLock lock];
NSString *name = [NSThread currentThread].name;
NSLog(@"%@开始卖%d号票",name,self.selledCount+1);
[NSThread sleepForTimeInterval:.5];
self.selledCount++;
NSLog(@"%@卖掉了%d号票 还剩%d张",name,self.selledCount,self.totalCount-self.selledCount);
// }
[self.myLock unlock];
}
}```

方法3:NSCondition
//声明属性
@property(nonatomic,strong)NSCondition *myCondition;
- (void)sellAction{
    while (YES) {
        //通过线程同步 让某段核心代码 只能有一个线程执行(加锁)
//        @synchronized(self) {
        [self.myCondition lock];
            NSString *name = [NSThread currentThread].name;
            NSLog(@"%@开始卖%d号票",name,self.selledCount+1);
            [NSThread sleepForTimeInterval:.5];
            self.selledCount++;
            NSLog(@"%@卖掉了%d号票 还剩%d张",name,self.selledCount,self.totalCount-self.selledCount);
//        }
        [self.myCondition unlock];
    }
}```
posted @ 2017-08-23 20:46  笑笑就好90  阅读(114)  评论(0编辑  收藏  举报