多线程-GCD总结

Wed 10 May 2017 by Little Captain

简介

  • 全称是Grand Central Dispatch,可译为“宏大的中枢调度器”
  • 纯C语言,提供了非常多强大的函数

GCD的优势

  • 苹果公司为多核的并行运算提出的解决方案
  • 自动利用更多的CPU内核
  • 自动管理线程的生命周期
    • 创建线程
    • 调度任务
    • 销毁线程
  • 使用方便 : 程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码

核心概念

任务

  • 执行什么操作

队列

  • 用来存放任务

类型

  • 并发队列
    • Concurrent Dispatch Queue
    • 可以让多个任务并发(同时)执行
    • 自动开启多个线程同时执行任务
    • 并发功能只有在异步(dispatch_async)函数下才有效
  • 串行队列
    • Serial Dispatch Queue
    • 让任务一个接着一个地执行
    • 一个任务执行完毕后,再执行下一个任务

同步和异步

  • 同步
    • 只能在当前线程中执行任务
    • 不具备开启新线程的能力
  • 异步
    • 可以在新的线程中执行任务
    • 具备开启新线程的能力

容易混淆的术语 …

read more

多线程-NSThread的使用

Wed 10 May 2017 by Little Captain

一个NSThread对象就代表一条线程

使用步骤

1. 创建线程

  • init
    • 具体使用: 自定义线程类继承自NSThread, 重写 main 方法(自定义任务、start 方法中会调用 main 方法)
  • initWithTarget

2. 启动线程

  • start
    • 必须要启动, 不然任务不会执行

相关方法

主线程相关

  • mainThread : 获取主线程
  • isMainThread : 类方法
  • isMainThread : 对象方法

其他方法

  • currentThread : 获取当前所在线程
  • setName : 设置线程名
  • name : 获取线程名

其他创建线程方式

  • detachNewThreadSelector

    • 创建线程后自动启动线程
    • 分离出子线程
  • performSelectorInBackground

    • 隐式创建并启动线程
    • 后台线程
  • 2种创建线程方式的优缺点

    • 优点 : 简单快捷
    • 缺点 : 无法拿到线程对象, 无法对线程进行更详细的设置

控制线程状态 …

read more

多线程-线程间通信

Wed 10 May 2017 by Little Captain

概念

在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信

具体应用

  • 1个线程传递数据给另1个线程
  • 在1个线程中执行完特定任务后,转到另1个线程继续执行任务

线程间通信常用方法

  • performSelectorOnMainThread
  • performSelector: onThread:
  • GCD 中直接通过线程嵌套来实现
read more

多线程-安全隐患

Tue 09 May 2017 by Little Captain

资源共享问题

  • 1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源
  • 比如: 多个线程访问同一个对象、同一个变量、同一个文件
  • 当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题

问题分析与解决

不加锁

安全隐患解决

加互斥锁

互斥锁使用

  • @synchronized(锁对象) {// 需要锁定的代码}
  • 锁定1份代码只用1把锁,用多把锁是无效的
  • 使用注意点
    • 注意加锁的位置
    • 注意加锁的前提条件 : 多条线程共享同一块资源
    • 注意加锁是需要代价的 : 需要耗费性能
    • 加锁的结果 : 线程同步了

互斥锁的优缺点

  • 优点 : 能有效防止因多线程抢夺资源造成的数据安全问题
  • 缺点 : 需要消耗大量的CPU资源

什么时候使用互斥锁

  • 多条线程抢夺同一块资源

线程同步

  • 多条线程在同一条线上执行(按顺序地执行任务)
  • 互斥锁,就是使用了线程同步技术

原子和非原子属性

atomic

  • 原子属性
  • 为setter方法加锁(默认就是atomic)

nonatomic

  • 非原子属性
  • 不会为setter方法加锁

原子和非原子属性的选择

nonatomic和atomic对比

  • atomic …
read more

多线程-iOS中的实现方案

Tue 09 May 2017 by Little Captain
方案 简介 语言 线程生命周期 使用频率
pthread 一套通用的多线程API
适用于Unix/Linux/Windows等系统
跨平台/可移植
使用难度大
C 程序员管理 几乎不用
NSThread 使用更加面向对象
简单易用,可直接操作线程对象
OC 程序员管理 偶尔使用
GCD 旨在替代NSThread等线程技术
充分利用设备的多核
C 自动管理 经常使用
NSOperation 基于GCD(底层是GCD)
比GCD多了一些更简单实用的功能
使用更加面向对象
OC 自动管理 经常使用
read more

多线程-iOS中的主线程

Tue 09 May 2017 by Little Captain
  • 一个iOS程序运行后,默认会开启1条线程, 称为“主线程”或“UI线程”

主线程的主要作用

  • 显示 / 刷新UI界面
  • 处理UI事件
    • 点击事件
    • 滚动事件
    • 拖拽事件

主线程的使用注意

  • 别将比较耗时的操作放到主线程中
  • 耗时操作会卡住主线程,严重影响UI的流畅度,给用户一种“卡”的坏体验
  • 耗时操作的执行
    • 如果将耗时操作放在主线程, 严重影响UI刷新
    • 如果将耗时操作放在子线程(后台线程、非主线程), 不影响UI刷新
read more

多线程-基本概念和原理

Tue 09 May 2017 by Little Captain

进程

  • 在操作系统中正在运行的一个应用程序
  • 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内

线程

  • 1个进程要想执行任务,必须得有线程
  • 每1个进程至少要有1条线程
  • 一个进程(程序)的所有任务都在线程中执行
  • 线程的串行
    • 1个线程中任务的执行是串行的
    • 如果要在1个线程中执行多个任务,那么只能一个一个地按顺序执行这些任务
    • 在同一时间内,1个线程只能执行1个任务
    • 也可以认为线程是进程中的1条执行路径

线程的状态

进程和线程的比较

  1. 线程是CPU调用(执行任务)的最小单位
  2. 进程是CPU分配资源和调度的单位
  3. 一个程序可以对应多个进程,一个进程中可以有多个线程,但至少要有一个线程
  4. 同一个进程内的线程共享进程的资源

多线程

  • 1个进程中可以开启多条线程,每条线程可以并行(同时)执行不同的任务
  • 比喻

    • 进程 : 车间
    • 线程 : 车间工人
  • 多线程技术可以提高程序的执行效率, 比如: 同时开启3条线程分别下载3个文件

多线程的原理

  • 同一时间,CPU只能处理1条线程,只有1条线程在工作(执行)
  • 多线程并发(同时)执行,其实是CPU快速地在多条线程之间调度 …
read more

一款基于 AFNetworking 封装的网络框架

Tue 09 May 2017 by Little Captain

框架地址

AFNetworking 存在的问题

如果你的项目中使用了 AFNetworking, 就一定会出现内存泄漏的问题. 这个是我在用做测试的时候发现的.

问题重现

  • 安装 AFNetworking, 使用 AFNetworking 做网络请求
  • 使用 Debug Memory Graph 查看内存引用关系

Debug Memory Graph(Xcode 8.0+)

![](../assets/images/LCNetworking/Debug Memory Graph.png)

AFNetworing 的一些对象被 Xcode 标记

图上结果表示: 这些对象无法被释放, 即内存泄漏.

  • 使用 Instrument 测试得到类似结果

解决问题

失败的解决办法

  • 控制器退出时, 取消所有任务
  • 使用 weak strong dance
  • ...

成功的解决办法 …

read more

UITableView 的性能优化

Tue 09 May 2017 by Little Captain

重要性

UITableView 是 iOS 开发中最常使用的控件之一, 在各类 App 中都充斥着各种表格. 表格展示的内容如果比较多, 比较复杂, 往往会影响界面的刷新帧率, 在用户的角度就是界面卡顿, 这时必须对 UITableView 进行性能优化.

表格为什么会卡?

iOS 设备的刷新帧率为 60Hz, 也就是一秒钟会有 60 帧图片绘制在屏幕上. 如果在下一帧图片绘制的时候, CPU正忙, 那么这一帧就会被跳过, 频繁出现这种情况, 界面就卡了. 总结: 在两帧之间运算没有做完, 就会出现跳帧

优化方向

实施优化的准则: 测量(主要是使用Instrument看帧率), 而不是猜测

关于计算

  • 尽量少计算, 所有需要的素材提前计算好!

关于圆角

  • 控件上不要设置圆角半径, 所有图像渲染的属性, 都要注意!

关于创建控件

  • 不要动态创建控件, 所有需要的控件, 都要提前创建好, 在显示的时候, 根据数据决定显示 / 隐藏

关于控件数量 …

read more

聊聊 iOS 的 MVC 架构

Tue 09 May 2017 by Little Captain

内容提要

这篇博文, 聊的是软件架构, 主要是 iOS 中的 MVC 架构.

架构基础

架构的目的

  • 解耦.
  • 类之间, 模块之间, 要交互, 就会有耦合. 我们的目标就是将耦合降到最低
  • 问题来了, 为什么要解耦呢? 解耦后的好处是什么? 个人总结两点: 1. 方便类和模块的重用; 2. 清晰化类之间、模块之间的逻辑关系, 便于维护、扩展

一些基本设计模式

在理解 MVC 这个复合设计模式之前, 有必要对下面的这些基本设计模式有一定的理解.

  • 代理(Delegate)
  • 通知(Notification)
  • 键值观察(KVO)
  • 目标动作(Target-Action)
  • ...

MVC

M : Model, 模型. 存放数据 V : View, 视图. 用户所见, 能给与用户进行交互 …

read more