美文网首页
iOS学习-多线程4

iOS学习-多线程4

作者: 快乐的tomato | 来源:发表于2021-09-15 12:42 被阅读0次

一、SDWebImage第三方框架

1、是什么

一个为UIImageView提供一个分类来支持远程服务器图片加载的库。
功能:

      1、一个添加了web图片加载和缓存管理的UIImageView分类
      2、一个异步图片下载器
      3、一个异步的内存加磁盘综合存储图片并且自动处理过期图片
      4、支持动态gif图
      5、支持webP格式的图片
      6、后台图片解压处理
      7、确保同样的图片url不会下载多次
      8、确保伪造的图片url不会重复尝试下载
      9、确保主线程不会阻塞

2、简单使用

#import "UIImageView+WebCache.h"

UIImageView *image = [[UIImageView alloc] init];
[image sd_setImageWithURL:[NSURL URLWithString:@"图片地址"] placeholderImage:[UIImage imageNamed:@"站位图"]];

3、工作流程

1、入口 setImageWithURL:placeholderImage:options: 会先把 placeholderImage 显示,然后 SDWebImageManager 根据 URL 开始处理图片。

2、进入 SDWebImageManager-downloadWithURL:delegate:options:userInfo:,交给 SDImageCache 从缓存查找图片是否已经下载 queryDiskCacheForKey:delegate:userInfo:.

3、先从内存图片缓存查找是否有图片,如果内存中已经有图片缓存,SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo: 到 SDWebImageManager。

4、SDWebImageManagerDelegate 回调 webImageManager:didFinishWithImage: 到 UIImageView+WebCache 等前端展示图片。

5、如果内存缓存中没有,生成 NSInvocationOperation 添加到队列开始从硬盘查找图片是否已经缓存。

6、根据 URLKey 在硬盘缓存目录下尝试读取图片文件。这一步是在 NSOperation 进行的操作,所以回主线程进行结果回调 notifyDelegate:。

7、如果上一操作从硬盘读取到了图片,将图片添加到内存缓存中(如果空闲内存过小,会先清空内存缓存)。SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo:。进而回调展示图片。

8、如果从硬盘缓存目录读取不到图片,说明所有缓存都不存在该图片,需要下载图片,回调 imageCache:didNotFindImageForKey:userInfo:。

9、共享或重新生成一个下载器 SDWebImageDownloader 开始下载图片。

10、图片下载由 NSURLConnection 来做,实现相关 delegate 来判断图片下载中、下载完成和下载失败。

11、connection:didReceiveData: 中利用 ImageIO 做了按图片下载进度加载效果。connectionDidFinishLoading: 数据下载完成后交给 SDWebImageDecoder 做图片解码处理。

12、图片解码处理在一个 NSOperationQueue 完成,不会拖慢主线程 UI。如果有需要对下载的图片进行二次处理,最好也在这里完成,效率会好很多。

13、在主线程 notifyDelegateOnMainThreadWithInfo: 宣告解码完成,imageDecoder:didFinishDecodingImage:userInfo: 回调给 SDWebImageDownloader。imageDownloader:didFinishWithImage: 回调给 SDWebImageManager 告知图片下载完成。

14、通知所有的 downloadDelegates 下载完成,回调给需要的地方展示图片。将图片保存到 SDImageCache 中,内存缓存和硬盘缓存同时保存。写文件到硬盘也在以单独 NSInvocationOperation 完成,避免拖慢主线程。

15、SDImageCache 在初始化的时候会注册一些消息通知,在内存警告或退到后台的时候清理内存图片缓存,应用结束的时候清理过期图片。

16、SDWI 也提供了 UIButton+WebCache 和 MKAnnotationView+WebCache,方便使用。

17、SDWebImagePrefetcher 可以预先下载图片,方便后续使用

参考:
[SDWebImage原理](https://www.jianshu.com/p/ff9095de1753?utm_source=desktop&utm_medium=timelin

二、死锁问题

1、什么是死锁?

线程卡住,不会往下执行

2、什么情况下会产生死锁?

使用sync函数往当前串行队列中添加任务,会卡住当前的串行对列,产生死锁,其他的基本不会。

  • 主队列的特点:
    先执行完主线程上的代码,才会执行主对列中的任务
  • dispatch_sync的特点
    立马在当前线程执行任务
 NSLog(@"任务1");
    //对列的特点:排队,FIFO,先进先出
    dispatch_sync(dispatch_get_main_queue(), ^{
        
        NSLog(@"任务2");
    });
    NSLog(@"任务2");

上面这段代码会崩掉,
因为根据主队列和dispatch_sync的特点,任务2和任务3会造成相互等待而不能动的情况,产生死锁。

三、相关面试题

1、你理解的多线程?
2、下面打印的结果是什么?

dispatch_queue_t queue = dispatch_queue_create("hahaha", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        
         NSLog(@"任务1==%@",[NSThread currentThread]);
        [self performSelector:@selector(Test) withObject:nil afterDelay:.0];
         NSLog(@"任务3==%@",[NSThread currentThread]);

       });

-(void)Test{
    NSLog(@"任务2==%@",[NSThread currentThread]);
}

2021-09-16 16:34:00.814177+0800 OCStudy[32750:3081015] 任务1==<NSThread: 0x6000009dda00>{number = 6, name = (null)}
2021-09-16 16:34:00.814845+0800 OCStudy[32750:3081015] 任务3==<NSThread: 0x6000009dda00>{number = 6, name = (null)}

结果只打印了1和3。

[self performSelector:@selector(Test) withObject:nil afterDelay:.0];
换成
[self performSelector:@selector(Test) withObject:nil];  //等价于   [self Test];

结果只打印1、2、3。
原因:
[self performSelector:@selector(Test) withObject:nil afterDelay:.0]
这句代码本质是往runloop里面添加了定时器,定时器只有在runloop中才能起作用,而子线程默认是没有启动runloop的,所以不起作用。

 dispatch_async(queue, ^{
        
         NSLog(@"任务1==%@",[NSThread currentThread]);
        [self performSelector:@selector(Test) withObject:nil afterDelay:.2];
         NSLog(@"任务3==%@",[NSThread currentThread]);

        //添加runloop
        [[NSRunLoop currentRunLoop] addPort:[[NSPort alloc] init] forMode:NSDefaultRunLoopMode];
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        
       });

添加runloop即可。

相关文章

  • iOS 多线程

    参考资料:iOS多线程iOS GCD 多线程问题在iOS中目前有4套多线程方案,他们分别是: PthreadsNS...

  • 整理

    KVO的实现原理与具体应用 2.通知 3.iOS多线程----NSOperation 4.iOS多线程----GC...

  • GeekBand - iOS 多线程和RunLoop 总结

    iOS 开发高级进阶 第三周 多线程 Runloop iOS 多线程以及 RunLoop 学习总结 基础知识 什么...

  • iOS基础-iOS程序生命周期

    iOS应用程序的生命周期又根据系统是否支持多线程分为两种: 不支持多线程的iOS4之前的系统以及支持多线程的iOS...

  • iOS多线程相关面试题

    iOS多线程demo iOS多线程之--NSThread iOS多线程之--GCD详解 iOS多线程之--NSOp...

  • 多线程之--NSOperation

    iOS多线程demo iOS多线程之--NSThread iOS多线程之--GCD详解 iOS多线程之--NSOp...

  • iOS多线程之--NSThread

    iOS多线程demo iOS多线程之--NSThread iOS多线程之--GCD详解 iOS多线程之--NSOp...

  • iOS学习-多线程4

    一、SDWebImage第三方框架 1、是什么 一个为UIImageView提供一个分类来支持远程服务器图片加载的...

  • iOS开发多线程篇-NSThread

    上篇我们学习了iOS多线程解决方式中的NSOperation,这篇我主要概况总结iOS多线程中NSThread的解...

  • iOS - 多线程(一):初识

    iOS - 多线程 系列文章 iOS - 多线程(一):初识iOS - 多线程(二):pthread、NSThre...

网友评论

      本文标题:iOS学习-多线程4

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