zoukankan      html  css  js  c++  java
  • iOS中的多线程及GCD

    多线程中的一些概念

        //任务:代码段  方法  线程就是执行这些任务

        //NSThread类 创建线程 执行线程

    [NSThread isMainThread]//判断是否是主线程

    #import "AppDelegate.h"
    
    @implementation AppDelegate
    -(void)dealloc
    {
        [_window release];
        [super dealloc];
    }
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
        // Override point for customization after application launch.
        self.window.backgroundColor = [UIColor whiteColor];
        
        //实现多线程
        //任务:代码段  方法  线程就是执行这些任务
        //NSThread类 创建线程 执行线程
        NSLog(@"-------------%d",[NSThread isMainThread]);//判断是否是主线程
        
        //实现多线程的方式一
        //使用 根类 NSObject 中的 performSelectorxxx方法
        //UI的刷新一定要在主线程里进行  子线程刷新UI会异常  刷新不了   或者延迟刷新.
    //    [self performSelectorInBackground:@selector(aa) withObject:nil];
        
        //实现多线程的方式二
        //使用 NSThread 类(多线程类)
        //创建一个线程 ,并让线程执行 self 的aa方法
        
        //线程分两种  脱离线程 和 非脱离线程
        //脱离线程;执行玩任务之后,自动销毁的线程
        //非脱离线程 : 执行完任务之后 ,不会被销毁的线程,可以后续执行别的任务
        //每一个线程都自带一个NSRunLoop对象,runloop默认是关闭的.一旦runloop开启,你的线程就会成为非脱离线程.runloop帮你轮询有没有新的任务分配到了这个线程里面
        
        //[NSThread detachNewThreadSelector:@selector(aa) toTarget:self withObject:nil];
        
        //创建一个线程,线程需要执行的任务是self 的aa 方法
    //    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(aa) object:nil];
    //    [thread start];//开始执行线程   解决了延迟执行的问题  在想执行的时候执行
        
        //第三种实现多线程的方式NSOperationQueue
        NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(aa) object:nil];
    //    [op1 start];
        
        NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"这是一个block operation");
        }];
        //线程同步就是串行  线程之间有依赖关系的时候使用同步 实现同步就把NSOperationQueue的MaxConcurrentOperationCount最大并发数为1
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    //    NSLog(@"~~~~~~~~~~~~~~~~~~~~~~~~%d",queue.maxConcurrentOperationCount);
        [queue setMaxConcurrentOperationCount:1];//设置最大并发数为1
        [queue addOperation:op1];//只需要把操作放到队列里即可,不需要人为调用start,queue会根据op的排队情况,帮你调用start .会智能帮为op安排线程
        [queue addOperation:op2];
        
        
        [self.window makeKeyAndVisible];
        return YES;
    }
    
    - (void)aa
    {
        //如果在子线程中执行任务 我们需要在任务里面加一个自动释放池
        //因为.线程与线程之间是相互独立的,但是资源是共享的,共享堆 空间 ,如果一个线程开辟了空间  没有释放  其他线程也无法 使用这块已经开辟的空间
        //尤其是当子线程里  大量使用便利构造器的时候 会导致很多堆空间无法回收内存
        //线程共享堆  ,栈不共享  每个子线程默认以栈的大小是512k  主线程栈大小事1M 栈主要是放 局部变量的,局部变量出了方法就会被销毁,因此,尽管只有512k或着1M但是已经够用的了 ,,栈空间的大小必须是4k的整数倍
        //
        @autoreleasepool {
            for (int i = 0; i<10; i++) {
                NSLog(@"%d",i);
            }
            NSLog(@"#################%d",[NSThread isMainThread]);
            
            [self performSelectorOnMainThread:@selector(bb) withObject:nil waitUntilDone:YES];
            NSLog(@"子线程结束了");
        }
    
    }
    - (void)bb
    {
        @autoreleasepool {
            NSLog(@"??????????????????????%d",[NSThread isMainThread]);
            for (int i = 0; i<20; i++) {
                NSLog(@"-%d",i);
            }
            NSLog(@"刷新你的UI");
        }
    
    }

    //GCD中的几个概念

     1.Queue         队列 dispatch Queue(分发队列)  若干个task

     2.Task          任务 (单独的方法或者代码段 block)

     3.Thread        线程

     GCD全程 Grand Central Dispatch

     Task是一个个单独的任务(函数. 方法 . block)

     Queue 里存放的是一个或者多个Task

     Thread ,为了保证Task能顺利执行,Queue会开辟适当的Thread,在开辟的Thread里面执行Task

     Queue分两种

     一.serialQueue(串行队列)

     特点:任务先进先出 ,排在前面的任务先执行,执行完之后,后面的任务才开始执行,即:任务1先执行,任务1执行完之后,任务2开始执行,任务2执行完之后,任务3开始执行,任务3执行完之后,任务4......

     二.concurrentQueue(并发队列)

     特点:任务先进先出,排载前面的任务先开始执行,一旦开始,后面的任务就开始执行(无需等前一个任务执行完毕).即:任务1先开始执行,无需等待任务1执行完,任务2就开始执行,无需等待任务2执行完,任务3就开始执行.无需等待任务3.......

     你把任务放到什么样的队列里,任务就会遵守这个队列的规则

    - (IBAction)method1:(id)sender {
        //如果想让任务串行,我们需要使用serialQueue
        //我们有2种途径获取serialQueue
        //方法1.使用系统自带的mainQueue(单例)
        //mainQueue智慧为任务(无论多少个任务)开辟一个线程,而且这个线程是主线程
        //思考: 这些任务 在主线程里面执行, 不会还会卡死主线程吗? 为什么系统还要给你提供mainQueue?
    //    dispatch_queue_t queue = dispatch_get_main_queue();
    //
    //    dispatch_async(queue, ^{
    //        NSLog(@"任务1 是否是主线程: %d  %@",[NSThread isMainThread],[NSThread currentThread]);
    //    });
    //    dispatch_async(queue, ^{
    //        NSLog(@"任务2 是否是主线程: %d  %@",[NSThread isMainThread],[NSThread currentThread]);
    //    });
    //    dispatch_async(queue, ^{
    //        NSLog(@"任务3 是否是主线程: %d  %@",[NSThread isMainThread],[NSThread currentThread]);
    //    });
    //    dispatch_async(queue, ^{
    //        NSLog(@"任务4 是否是主线程: %d  %@",[NSThread isMainThread],[NSThread currentThread]);
    //    });
    //    dispatch_async(queue, ^{
    //        NSLog(@"任务5 是否是主线程: %d  %@",[NSThread isMainThread],[NSThread currentThread]);
    //    });
        
        //方法2.自己创建一个serialQueue
        //自己创建的serialQueue也只为任务(无论多少个任务)开辟一个线程,这些线程是在子线程里执行的,既不会卡死主线程,也能实现线程同步
        //GCD中函数带create 要用release释放
    //    dispatch_queue_t queue = dispatch_queue_create("com.limice.mySerialQueue", DISPATCH_QUEUE_SERIAL);
    //    dispatch_async(queue, ^{
    //        NSLog(@"任务1 是否是主线程: %d  %@",[NSThread isMainThread],[NSThread currentThread]);
    //    });
    //    dispatch_async(queue, ^{
    //        NSLog(@"任务2 是否是主线程: %d  %@",[NSThread isMainThread],[NSThread currentThread]);
    //    });
    //    dispatch_async(queue, ^{
    //        NSLog(@"任务3 是否是主线程: %d  %@",[NSThread isMainThread],[NSThread currentThread]);
    //    });
    //    dispatch_async(queue, ^{
    //        NSLog(@"任务4 是否是主线程: %d  %@",[NSThread isMainThread],[NSThread currentThread]);
    //    });
    //    dispatch_async(queue, ^{
    //        NSLog(@"任务5 是否是主线程: %d  %@",[NSThread isMainThread],[NSThread currentThread]);
    //    });
        //释放GCD中所有通过create创建的对象
    //    dispatch_release(queue);
    }
    - (IBAction)method2:(id)sender {
        //如果想并发执行任务,我们使用concurrentQueue.
        //获得concurrentQueue的途径仍然有两种
        //第一种:使用系统自带的globalQueue(单例)
    //    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
        //第二种:使用自己创建的concurrentQueue
        dispatch_queue_t queue = dispatch_queue_create("com.limice.myConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_async(queue, ^{
            NSLog(@"任务1 是否是主线程: %d  %@",[NSThread isMainThread],[NSThread currentThread]);
            dispatch_queue_t mainQueue = dispatch_get_main_queue();
            dispatch_async(mainQueue, ^{
                NSLog(@"刷新你的UI");
            });
        });
        dispatch_async(queue, ^{
            NSLog(@"任务2 是否是主线程: %d  %@",[NSThread isMainThread],[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务3 是否是主线程: %d  %@",[NSThread isMainThread],[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务4 是否是主线程: %d  %@",[NSThread isMainThread],[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务5 是否是主线程: %d  %@",[NSThread isMainThread],[NSThread currentThread]);
        });
        dispatch_release(queue);
    }
    - (IBAction)method3:(id)sender {
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        //延迟执行(3s)
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"2222222222");
        });
    
        
    }
    - (IBAction)method4:(id)sender {
        NSArray *arr = @[@"红楼梦",@"水浒传",@"西游记",@"三国演义",@"封神演义"];
        
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        //重复执行一个任务
        dispatch_apply(5, queue, ^(size_t t) {
            NSLog(@"%@",arr[t]);
        });
    }
    - (IBAction)method5:(id)sender {
        //给任务分组
        dispatch_group_t group = dispatch_group_create();
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
        dispatch_group_async(group, queue, ^{
            NSLog(@"任务1");
        });
        dispatch_group_async(group, queue, ^{
            NSLog(@"任务2");
        });
    
        dispatch_group_async(group, queue, ^{
            NSLog(@"任务3");
        });
        dispatch_group_async(group, queue, ^{
            NSLog(@"任务4");
        });
        dispatch_group_async(group, queue, ^{
            NSLog(@"任务5");
            
        });
        dispatch_group_async(group, queue, ^{
            NSLog(@"任务6");
        });
        dispatch_async(queue, ^{
            NSLog(@"任务4 是否是主线程: %d  %@",[NSThread isMainThread],[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"任务5 是否是主线程: %d  %@",[NSThread isMainThread],[NSThread currentThread]);
        });
        dispatch_group_notify(group, queue, ^{
            NSLog(@"走,出发");
        });
    }
    - (IBAction)method6:(id)sender {
        dispatch_queue_t queue = dispatch_queue_create("com.limice.myConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_async(queue, ^{
            NSLog(@"所有男同学同学,是否主线程 %d %@",[NSThread isMainThread],[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"年龄20岁以上的同学,是否主线程 %d %@",[NSThread isMainThread],[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"河南的同学,是否主线程 %d %@",[NSThread isMainThread],[NSThread currentThread]);
        });
        dispatch_barrier_async(queue,^{
            NSLog(@"写入");
        });
        dispatch_async(queue, ^{
            NSLog(@"月薪上万的同学,是否主线程 %d %@",[NSThread isMainThread],[NSThread currentThread]);
        });
    
    }
    - (IBAction)method7:(id)sender {
        //用来写单例
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            NSLog(@"hello");
        });
    }
    - (IBAction)method8:(id)sender {
        dispatch_queue_t queue = dispatch_queue_create("com.limice.myConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
        //同步(串行):必须等block执行完,才执行后面的语句
        //异步就是并行
        dispatch_sync(queue, ^{
            for (int i = 0; i<10; i++) {
                NSLog(@"%d",i);
            }
        });
        NSLog(@"over");
    }
    - (IBAction)method9:(id)sender {
        dispatch_queue_t queue = dispatch_queue_create("com.limice.myConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_async_f(queue, @"hello world", aa);
    }
    void aa(void *context)
    {
        NSLog(@"%@",context);
    }
  • 相关阅读:
    python快速查看内置模块函数
    kettle -小技巧 null 跳过唯一索引
    IOException:Connection refused:connect Kettle连接数据库
    各种数据库的jdbc驱动下载及连接方式
    DataCleaner中文文档
    ModuleNotFoundError: No module named 'xlwt' 。
    liunx 常用命令
    Mysql 环境搭建详解
    查询mysql所有表数据、字段信息
    mysqp pk、nn、qu、b、un、zf、ai、g代表的意思
  • 原文地址:https://www.cnblogs.com/limicheng/p/3895588.html
Copyright © 2011-2022 走看看