美文网首页
iOS 多线程的概念、原理

iOS 多线程的概念、原理

作者: 尤先森 | 来源:发表于2019-03-12 21:22 被阅读0次
    图1.png

    线程和进程的关系和区别

    线程定义
    • 线程是进程的基本执行单元,一个进程的所有任务都在线程中执行
    • 进程要想执行任务,必须得有线程,进程至少要有一条线程
    • 程序启动会默认开启一条线程,这条线程被称为主线程或 UI 线程
    进程定义
    • 进程是指在系统中正在运行的一个应用程序
    • 每个进程之间是独立的,每个进程均运行在其专用的且受保护的内存空间内
    • 通过“活动监视器”可以查看 Mac 系统中所开启的进程
    进程与线程的区别
    • 地址空间:同一进程的线程共享本进程的地址空间,而进程之间则是独立的地址空间。
    • 资源拥有:同一进程内的线程共享本进程的资源如内存、I/O、cpu等,但是进程之间的资源是独立的。
    • 一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。
    • 进程切换时,消耗的资源大,效率高。所以涉及到频繁的切换时,使用线程要好于进程。同样如果要求同时进行并且又要共享某些变量的并发操作,只能用线程不能用进程
    • 执行过程:每个独立的进程有一个程序运行的入口、顺序执行序列和程序入口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
    • 线程是处理器调度的基本单位,但是进程不是。

    多线程的意义

    优点

    • 能适当提高程序的执行效率
    • 能适当提高资源的利用率(CPU,内存)
    • 线程上的任务执行完成后,线程会自动销毁

    缺点

    • 开启线程需要占用一定的内存空间(默认情况下,每一个线程都占 512 KB)
    • 如果开启大量的线程,会占用大量的内存空间,降低程序的性能
    • 线程越多,CPU 在调用线程上的开销就越大
    • 程序设计更加复杂,比如线程间的通信、多线程的数据共享


      图2.png

    好像主线程也是512KB,而不是1MB

    多线程的原理
    图3.png
    多线程的生命周期
    图4.png
    • 新建线程,执行start,线程必须start,否则没有作用。但也不可以重复start,会导致崩溃
    • 线程start后,将会进入Runnable状态。
    • 进入Runnable状态后,进入Running状态,当前线程会被CPU调度。也有可能在进入Running状态后,线程切换,返回Runnable状态

    CPU如何调度线程?线程池的原理

    图5-线程池参数.png
    图6-线程池的原理.png
    1.系统有一个可调度线程池,如果线程池里有这个线程,就会开始执行。
    2.如果没有,将判断线程池大小是否小于核心线程池大小,如果小于,那将会开辟新的线程来执行任务。
    3.如果大于线程池,代表线程池没有能力再去开辟新的线程,只能依赖于原有的线程去执行 ,就将判断工作队列是否已满,如果没满就将任务提交到工作队列,等待执行任务。
    4.满了的话,线程池就会判断所有线程是否都在工作,如果有空闲的线程,就让这条线程去执行任务。
    5.如果还是没有空闲的线程,就将任务交给饱和策略
    6.饱和策略分为四种

    Abort策略:默认策略,新任务提交时直接抛出未检查的异常RejectedExecutionException,该异常可由调用者捕获。
    CallerRuns策略:为调节机制,既不抛弃任务也不抛出异常,而是将某些任务回退到调用者。不会在线程池的线程中执行新的任务,而是在调用exector的线程中运行新的任务。
    Discard策略:新提交的任务被抛弃。
    DiscardOldest策略:队列的是“队头”的任务,然后尝试提交新的任务。(不适合工作队列为优先队列场景)

    • Running后,有可能任务会造成堵塞,当造成堵塞的任务执行结束后,同样会回到Runnable状态,继续执行Running
    • 死亡,分为任务执行结束跟强制退出线程exit

    线程操作

    查看NSThread相关文件可以看到,线程有多种状态,可以根据不同情况,判断线程的状态,来做不同的操作。可通过重写下面的方法掌握线程的生命周期(YYKit)。
    一般情况下,我们很少去中止一个网络请求,按照一般的情况,是没办法中止的,但是依靠线程,通过关闭线程,从而达到中止网络请求的目的。

    @property (readonly, getter=isExecuting) BOOL executing API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
    @property (readonly, getter=isFinished) BOOL finished API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
    @property (readonly, getter=isCancelled) BOOL cancelled API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
    
    - (void)cancel API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
    - (void)start API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
    - (void)main API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0)); // thread body method
    

    线程安全

    这是一张经典的多线程比喻图。多端增删改查。


    图7.png

    如何避免上图的情况?如何保证线程安全?
    上锁

    相关文章

      网友评论

          本文标题:iOS 多线程的概念、原理

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