zoukankan      html  css  js  c++  java
  • 多线程

    多线程

    1.多线程

      pthread

      NSThread

      NSOPeration

      GCD--支持多核

    2.NSThread

      (1)

        //NSThread多线程的使用

        //1.创建线程

    #pragma mark - 1.创建线程
    -(void)createThread{
        
        //*******顺序执行(串行执行)*/
    //    [self taskA];
    //   [self taskB];
        
        //*******并行执行(多个任务同时执行)********/
        //创建新的线程
        //方式一(创建之后不会立即执行)
        NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(taskA) object:nil];
        [thread1 start];
        //方式二(创建之后立即执行)
        //需设置Object:thread1  --> 线程之间的控制与通信
        [NSThread detachNewThreadSelector:@selector(taskB:) toTarget:self withObject:thread1];
    }
    -(void)taskA{
    
        for(int i=0;i<20;i++){
        
            NSLog(@"A = %d",i);
            
    //        每次检测是否应该取消
            if([NSThread currentThread].isCancelled){   //取出当前线程--> 是否取消(若是,exit线程)
            
                [NSThread exit];  //退出线程
            }
    
            [NSThread sleepForTimeInterval:0.25];
        }
    }
    -(void)taskB:(NSThread *)thread{
        
        for(int i=0;i<20;i++){
            
            NSLog(@"B = %d",i);
            if(i==10){
            
                [thread cancel];   //线程B,发送cancel消息
              //  NSLog(@"tadkB: %@ , thread = %@",[NSThread currentThread],thread);
            }
            [NSThread sleepForTimeInterval:0.25];
        }
    }

      (2)为何使用多线程,解决什么问题

    #pragma mark - 2.为何使用多线程,解决什么问题
    -(void)whyUseThread{
    
        //本质:  多线程主要解决 执行耗时任务时出现的UI界面阻塞的问题
        //       或同时执行多个任务(如 迅雷)
        //使用场景: 大麦网 -- 下载数据(耗时5s),图片(耗时10s)
        //         迅雷加载视频文件
        
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
        [btn setTitle:@"耗时任务" forState:UIControlStateNormal];
        btn.frame = CGRectMake(100, 100, 100, 30);
        [btn addTarget:self action:@selector(startTask:) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:btn];
        
    }
    -(void)startTask:(id)sender{
    
        //http://10.3.8.8/download/真机调试.tar.gz
        NSString *urlString = @"http://10.3.8.8/download/真机调试.tar.gz";
        //只能放在子线程,会卡
        NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:urlString]];
        NSLog(@"size = %u",data.length);
        
    }

      (3)使用通知监听线程结束

        //3.使用通知监听线程结束
    //    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dealTheardExit) name:NSThreadWillExitNotification object:nil];
    #pragma mark - 3.使用通知监听线程结束
    -(void)dealTheardExit{
    
        NSLog(@"线程结束");
    }

      (4)线程的控制和通信

    //4.线程的控制和通信
        //  A --> i=10时,B stop

      (5)

     //5.线程的同步锁
        //多个线程访问同一块内存 --> 解决(NSLock 锁)
        _lock = [[NSLock alloc] init];
    //    [NSThread detachNewThreadSelector:@selector(add) toTarget:self withObject:nil];
    //    [NSThread detachNewThreadSelector:@selector(sub) toTarget:self withObject:nil];
    #pragma mark - 5.线程的同步锁
    -(void)add{
    
        for(int i=0;i<1000;i++){
            
            [_lock lock];   //加锁
            _num++;
            NSLog(@"add = %d",_num);
            [_lock unlock];  //解锁
        }
    }
    -(void)sub{
        
        for(int i=0;i<1000;i++){
            
            [_lock lock];
            _num--;
            NSLog(@"sub = %d",_num);
            [_lock unlock];
        }
    }

      (6)

        //6.子线程如何更新UI(very import)
        //限制 : UI线程--> 主线程
        //       其他创建的线程--子线程
        //      注:不要在子线程直接操作UI--> 让主线程操作
        //下载进度更新
    //    [NSThread detachNewThreadSelector:@selector(downloadNetWorkData) toTarget:self withObject:nil];
        // [self downloadNetWorkData];
        _progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(10, 200, 300, 20)];
        [self.view addSubview:_progressView];
    #pragma mark - 6.
    -(void)downloadNetWorkData{
        
        for(int i=0;i<100;i++){
        
            [self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:YES];   //在主线程里改变UI
            [NSThread sleepForTimeInterval:0.1];  //
        }
    }

    3.NSOperation

    //************************NSOperation使用************************/
        //***1.NSOperation  --> NSThread类似,实现多线程的机制。。更抽象,加入了block,更简单易用
        
        //***2.NSOperation抽象类-->NSInvocationOperation,NSBlockOperation
        //NSInvocationOperation
        NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task1) object:nil];
    //    [invocationOperation start];   //创建之后需要执行-->start ,默认同步执行
        
        //NSBlockOperation
        NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
            
            for(int i=0;i<20;i++){
                
                NSLog(@"B = %d",i);
            }
        }];
    //    [blockOperation start];   //同上,默认同步执行
        
        //NSOperationQueue --> 操作队列,任务列表(注:异步平行执行)
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        [queue addOperation:invocationOperation];  //添加队列
        [queue addOperation:blockOperation];
        

    4.GCD

        //*****GCD的使用  --> Grand Central Dispatch  *******/
        //  好处: 1.支持多核; 2.C和block,易于使用 ; 3.较晚出现,功能强大,使用多
        
        //1.GCD 创建异步任务
    //   [self createAsyncTask];
        
        //2.模拟网络下载
    //    [self simulateNetWorkDownload];
        
        //3.只执行一次
        [self runOnce];
        
        //4.延迟执行
        [self delayRun];
        
        //5.同时执行多个任务,等待所有任务执行完成进行处理
        //eg: 迅雷所有任务完成自动关机
        [self groupRun];
    #pragma mark - 5.同时执行多个任务,等待所有任务执行完成进行处理
    -(void)groupRun{
    
        //group
        dispatch_group_t group = dispatch_group_create();   //添加到group
        //添加任务 7s
        dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            for(int i=0;i<100;i++){
            
                NSLog(@"A = %d",i);
                [NSThread sleepForTimeInterval:0.07];
            }
        });
        //  5s
        dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            for(int i=0;i<100;i++){
                
                NSLog(@"B = %d",i);
                [NSThread sleepForTimeInterval:0.05];
            }
        });
        //  10s
        dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            for(int i=0;i<100;i++){
                
                NSLog(@"C = %d",i);
                [NSThread sleepForTimeInterval:0.1];
            }
        });
    
        //
        dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            NSLog(@"自动关机");
        });
        
    }
    
    #pragma mark - 4.延迟执行
    -(void)delayRun{
    
        //延迟5s 执行
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"he he he");
        });
    }
    
    #pragma mark - 3.只执行一次
    -(void)runOnce{
    
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            NSLog(@"只执行一次的代码");
        });
        
    }
    
    #pragma mark - 2.模拟网络下载
    -(void)simulateNetWorkDownload{
    
        UIProgressView *progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(10, 100, 300, 20)];
        [self.view addSubview:progressView];
        
        //GCD开启最简单的异步任务下载   主线程
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_async(queue, ^{
            //在子线程中执行
            for(int i=0;i<100;i++){
               //返回主线程执行
               dispatch_async(dispatch_get_main_queue() , ^{
                   
                   progressView.progress += 0.01;
                   NSLog(@"progress = %f",progressView.progress);
               });
                
                [NSThread sleepForTimeInterval:0.1];
            }
            
            //最后显示对话框(子线程--> 需要切回main)
            dispatch_async(dispatch_get_main_queue(), ^{
                UIAlertView *alert = [[UIAlertView alloc] init];
                alert.message = @"下载完成";
                [alert addButtonWithTitle:@"取消"];
                [alert show];
            });
            
        });
    
    }
    
    #pragma mark - 1.GCD 创建异步任务
    -(void)createAsyncTask{
    
        //参数1:  dispatch_queue_t queue  --> 有3种queue
        //              mian_queue 主队列(主线程), glabel_queue 全局队列(工作线程),自定义queue
        //参数2:  ^(void)block
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        //执行异步任务
        dispatch_async(queue, ^{
           
            for(int i=0;i<20;i++){
            
                NSLog(@"A = %d",i);
            }
        });
        
        dispatch_async(queue, ^{
            
            for(int i=0;i<20;i++){
                
                NSLog(@"B = %d",i);
            }
        });
    
    }
  • 相关阅读:
    java中的锁
    CAS机制与自旋锁
    volatile关键字的特性及证明
    java中并发下的集合类
    数据库的分库分表
    浅入理解JVM
    99乘法表
    JAVA实现简单的时间刷新使用线程
    线程的优先级
    线程礼让
  • 原文地址:https://www.cnblogs.com/wlrBlogs/p/4427760.html
Copyright © 2011-2022 走看看