zoukankan      html  css  js  c++  java
  • 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];
        }
    }```
    成功的三大原则: 1、坚持 2、不要脸 3、坚持不要脸
  • 相关阅读:
    c# webapi 在swagger里添加全局过滤器
    axios get,post请求时带headers
    svn"重新定位"提示版本库uuid不匹配
    DevExpress XtraReport
    DevExpress GridControl List绑定方式下新增行的方法
    对Dev的GridControl/GridView控件进行分组并展开操作
    DevExpress GridControl控件行内新增、编辑、删除添加选择框
    JavaScript 中的FileReader对象(实现上传图片预览)
    数据库连接情况查询
    C#代码中实现两个表(DataTable)的关联查询(JOIN)
  • 原文地址:https://www.cnblogs.com/xulinmei/p/7420112.html
Copyright © 2011-2022 走看看