美文网首页
05-多线程(1)

05-多线程(1)

作者: cdd48b9d36e0 | 来源:发表于2017-02-03 17:26 被阅读10次

    0708-GCD单例模式

    1、概述(01-多线程的基本概念)

    • 多线程如果掌握得不好对一些性能方面的东西会做的不好
    • 一个两到三年的IOS开发者最常问:
    • 事件处理:响应者链条
    • Runtime
    • RunLoop:多线程
    • 一个运行中的程序就是一个进程,程序要执行任务就必须开辟线程来执行,一个进程至少有一条线程
    • 一条线程对象即使他是局部变量,他会在任务完成时自动销毁
    • 一条线程中多个任务的执行是串行的
    • 一个进程可以开辟多条线程,每条线程并行执行不同的任务
    • 多线程开发的缺点
    • CPU需要调度N多线程会消耗大量CPU资源
    • 每条线程被调度执行的次数降低(线程执行效率降低)
    • 创建线程是有开销的,iOS下主要成本包括:内核数据结构(大约1KB)、栈空间(子线程512KB、主线程1MB,也可以使用-setStackSize:设置,但必须是4K的倍数,而且最小是16K),创建线程大约需要90毫秒的创建时间
    • 程序设计更加复杂:比如线程之间的通信、多线程的数据共享
    • 多线程开发的优点
    • 适当提高程序执行效率
    • 每条线程被调度执行的次数降低(线程执行效率降低)
    • 主线程的作用
    • 显示\刷新UI界面
    • 处理UI事件(比如点击事件、滚动事件、拖拽事件等)

    2、iOS中多线程的实现方案(03-多线程的实现方案)

    3、线程的状态(06-线程的状态)

    4、线程之间的通信方式(08-线程间的通信)

    • NSThread
     - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        [self performSelectorInBackground:@selector(download3) withObject:nil];
    }
     - (void)download3
    {
        // 图片的网络路径
        NSURL *url = [NSURL URLWithString:@"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg"];
        
        // 加载图片
        NSData *data = [NSData dataWithContentsOfURL:url];
        
        // 生成图片
        UIImage *image = [UIImage imageWithData:data];
        
        // 回到主线程,显示图片
        [self.imageView performSelector:@selector(setImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:NO];
    //    [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];
    //    [self performSelectorOnMainThread:@selector(showImage:) withObject:image waitUntilDone:YES];
    }
    
    • GCD
     - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            // 图片的网络路径
            NSURL *url = [NSURL URLWithString:@"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg"];
            
            // 加载图片
            NSData *data = [NSData dataWithContentsOfURL:url];
            
            // 生成图片
            UIImage *image = [UIImage imageWithData:data];
            
            // 回到主线程
            dispatch_async(dispatch_get_main_queue(), ^{
                self.imageView.image = image;
            });
        });
    }
    
    • NSPort(端口),比较复杂、现在很少用
    • NSMessagePort;
    • NSMachPort;

    5、各种队列的执行效果(10-gcd的各种队列)

    6、GCD的其他常用函数(12-gcd常用函数)

    • dispatch_barrier_async
     - (void)barrier
    {
        dispatch_queue_t queue = dispatch_queue_create("12312312", DISPATCH_QUEUE_CONCURRENT);
        
        dispatch_async(queue, ^{
            NSLog(@"----1-----%@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"----2-----%@", [NSThread currentThread]);
        });
        //先执行barrier之前的,再执行barrier,最后执行barrier之后的,需要注意一点的是queue不能是全局的并发队列
        dispatch_barrier_async(queue, ^{
            NSLog(@"----barrier-----%@", [NSThread currentThread]);
        });
        
        dispatch_async(queue, ^{
            NSLog(@"----3-----%@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"----4-----%@", [NSThread currentThread]);
        });
    }
    
    • 延时执行
    • 调用NSObject的方法
    • 使用GCD函数
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        // 2秒后异步执行这里的代码...
    });
    
    • 定时器
      [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:NO];
    • 一次性代码
     - (void)once
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            NSLog(@"------run");
        });
    }
    
    • 快速迭代(利用多线程并发执行循环遍历)
    /**
     * 使用GCD快速迭代剪切
     */
     - (void)apply
    {
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        NSString *from = @"/Users/xiaomage/Desktop/From";
        NSString *to = @"/Users/xiaomage/Desktop/To";
        
        NSFileManager *mgr = [NSFileManager defaultManager];
        NSArray *subpaths = [mgr subpathsAtPath:from];
        
        dispatch_apply(subpaths.count, queue, ^(size_t index) {
            NSString *subpath = subpaths[index];
            NSString *fromFullpath = [from stringByAppendingPathComponent:subpath];
            NSString *toFullpath = [to stringByAppendingPathComponent:subpath];
            // 剪切
            [mgr moveItemAtPath:fromFullpath toPath:toFullpath error:nil];
            
            NSLog(@"%@---%@", [NSThread currentThread], subpath);
        });
    }
    /**
     * 传统文件剪切
     */
     - (void)moveFile
    {
        NSString *from = @"/Users/xiaomage/Desktop/From";
        NSString *to = @"/Users/xiaomage/Desktop/To";
    
        NSFileManager *mgr = [NSFileManager defaultManager];
        NSArray *subpaths = [mgr subpathsAtPath:from];
    
        for (NSString *subpath in subpaths) {
            NSString *fromFullpath = [from stringByAppendingPathComponent:subpath];
            NSString *toFullpath = [to stringByAppendingPathComponent:subpath];
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                // 剪切
                [mgr moveItemAtPath:fromFullpath toPath:toFullpath error:nil];
            });
        }
    }
    
    • 队列组
     - (void)group
    {
        
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        // 创建一个队列组
        dispatch_group_t group = dispatch_group_create();
        
        // 1.下载图片1
        dispatch_group_async(group, queue, ^{
            // 图片的网络路径
            NSURL *url = [NSURL URLWithString:@"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg"];
            
            // 加载图片
            NSData *data = [NSData dataWithContentsOfURL:url];
            
            // 生成图片
            self.image1 = [UIImage imageWithData:data];
        });
        
        // 2.下载图片2
        dispatch_group_async(group, queue, ^{
            // 图片的网络路径
            NSURL *url = [NSURL URLWithString:@"http://pic38.nipic.com/20140228/5571398_215900721128_2.jpg"];
            
            // 加载图片
            NSData *data = [NSData dataWithContentsOfURL:url];
            
            // 生成图片
            self.image2 = [UIImage imageWithData:data];
        });
        
        // 3.将图片1、图片2合成一张新的图片
        dispatch_group_notify(group, queue, ^{
            // 开启新的图形上下文
            UIGraphicsBeginImageContext(CGSizeMake(100, 100));
            
            // 绘制图片
            [self.image1 drawInRect:CGRectMake(0, 0, 50, 100)];
            [self.image2 drawInRect:CGRectMake(50, 0, 50, 100)];
            
            // 取得上下文中的图片
            UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
            
            // 结束上下文
            UIGraphicsEndImageContext();
            
            // 回到主线程显示图片
            dispatch_async(dispatch_get_main_queue(), ^{
                // 4.将新图片显示出来 
                self.imageView.image = image;
            });
        });
    }
    

    7、单例模式(14-gcd实现单例模式)

    在IOS里面单例有几种实现方式,最常用的就是GCD来实现。什么是设计模式?长期积累的一种经验。

    1. 步骤(ARC)
    • static id _instance;
    • 重写allocWithZone(重新alloc)
    • 给外界重写一个公用方法+ (instancetype)sharedInstance
    • 重新copyWithZone(重新copy方法)
    1. 重新alloc方法只需要重写allocWithZone方法
     + (instancetype)allocWithZone:(struct _NSZone *)zone
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _person = [super allocWithZone:zone];
        });
        return _person;
    }
    
    1. 在一个专门的h文件里用宏定义单例
    // .h文件
    #define XMGSingletonH(name) + (instancetype)shared##name;
    / .m文件
    #define XMGSingletonM(name) \
    static id _instance; \
     \
     + (instancetype)allocWithZone:(struct _NSZone *)zone \
    { \
        static dispatch_once_t onceToken; \
        dispatch_once(&onceToken, ^{ \
            _instance = [super allocWithZone:zone]; \
        }); \
        return _instance; \
    } \
     \
     + (instancetype)shared##name \
    { \
        static dispatch_once_t onceToken; \
        dispatch_once(&onceToken, ^{ \
            _instance = [[self alloc] init]; \
        }); \
        return _instance; \
    } \
     \
     - (id)copyWithZone:(NSZone *)zone \
    { \
        return _instance; \
    }
    //static 让外界即使通过extern都不能访问
    

    相关文章

      网友评论

          本文标题:05-多线程(1)

          本文链接:https://www.haomeiwen.com/subject/fxpdittx.html