浅析多线程


为什么要使用多线程?
—>提高用户效率
—>提高用户交互
耗时操作会使界面卡
1.空的for循环补耗时
2.NSLog是耗时的  因为NSLog是一个I/o操作,即那个数据从内存中输入或者输出到外接设备.
3.耗时操作卡死主屏幕
4.解决办法:实现了多线程技术,解决了屏幕卡死的问题
5.学习多线程的目的:解决耗时操作卡死屏幕的问题.将耗时操作放在后台执行.
6.网络下载是非常耗时的 在学习网络或者网络开发的过程中,用多线程,不卡

多线程概念
1.同步/异步(任务或者代码执行的方式)
同步:多个任务按需依次执行,执行任务有先后顺序
异步:执行任务同时执行,多个人同时执行多个任务

2.进程/线程

进程(类比成公司(正常运营的))
->进程是指在系统中正在运行的一个应用程序
->每个进程之间是独立的,每个进程均运行在其专用的且受保护的内存空间内

线程(类比成公司的员工)
老板是主线程
->一个进程可以有多个线程组成(一个进程至少要有一个线程)
->线程是进程的基本执行单元,一个进程的所有任务都在线程中执行

3.多线程
->一个进程中可以开启多个线程,多个线程可以”同时”执行不同的任务
->多线程可以解决程序阻塞的问题
->多线程可以适当的提高程序的执行效率


多线程工作原理
->是CPU快速的在多个线程之间的切换
->由于执行的速度快,就早造成了同时执行的一种假象
->如果线程数非常多,CPU会在会在多个线程之间切换,消耗大量的CPU资源
   ->每一个线程被调度的次数会降低,线程的执行效率降低

多线程的优点和缺点
优点
->能适当提高程序的执行效率
->能适当提高资源的利用率(CPU 内存)
->线程上的任务执行完成后,线程UI自动销毁

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

建议:多线程不是越多越好,只在适当的时候开启多线程(耗时操作的时候)

主线程
->一个程序运行后,默认会开启一个线程,成为"主线程”或者"UI线程"
->主线程一般用来刷新UI界面,处理UI事件(比如:点击 滚动 拖拽等事件)
->子线程在执行耗时操作
注意:
->别将耗时操作放到主线程中

IOS中多线程的技术方案

1.pthread
 —>导入头文件  #include <pthread.h>
第一个参数:子线程的编号/代号/ID,传入地址
第二个参数:子线程的属性,传入地址  .NULL,空指针    nil,空对象
第三个参数:指定子线程执行的对象
        void *      (*)         (void *)
       返回值    函数名    函数的参数
        void * : 是C语言中,可以指向任何地址的指针.类似于OC中的id(万能对象指针,可以指向任何对象的地址)
        函数的地址就是函数名
第四个参数:传入到指定子线程执行的函数的参数

该方法的返回值是: int 创建子线程成功返回0,失败返回非0;
<NSThread: 0x7fa9a270a870>{number = 2, name = (null)}
      number != 1.代表当前线程是子线程
<NSThread: 0x7fcf72202bf0>{number = 1, name = main}
      number = 1.代表当前线程是主线程
建议 : 千万不要纠结number到底等于几.

__bridge : 桥接

MRC : 谁申请,谁释放

ARC : 编译器在编译代码的时候,会根据的代码结构自动的添加release,retain,autorelease语句

ARC环境下,编译器不会处理C语言申请的内存空间.我们做C语言和OC语言混合开发的时候,需要使用桥接

目的 : 告诉编译器如何处理内存.即,什么都不做.

提问 : MRC环境下使用桥接吗? 

        不需要.因为内存手动管理的

2.NSThread
创建线程的三种方式
方式1:对象方法创建
         启动线程对象:[thread start];
方式2:类方法创建
         detach  :  分离
         这种创建线程的方式无法获取到对象,自动启动线程.
方式3:隐式创建
         这种创建线程的方法继承自:
         @interface NSObject (NSThreadPerformAdditions)
         任何继承自 NSObject 的对象都可以很方便的创建线程对象

共享资源
资源:一个对象  一个变量   一个文件
共享资源:全局的变量 对象  文件 ,可以被其他对象访问的资源
->一块资源可能会被多个线程共享,也就是多个线程可能会操作同一     块资源

注:当多个线程操作同一块资源师,很容易引发数据错乱和数据安全问题,为了解决这一问题,引入”锁”的概念
1.互斥锁(线程同步)
互斥锁能有效防止因多线程抢夺资源造成的数据安全问题
线程同步:多条线程按顺序执行任务

self : 锁对象.任何继承自NSObject的对象都是锁对象.因为内部都有一把锁,默认是开启的

锁对象必须是全局的.self是最方便的全局的锁对象

特点 : 能够保证被锁定的代码,在同一时间,只有一个线程可以操作

使用原则 : 必须锁定共享资源的读写部分,而且锁定的范围必须小

补充 : 加锁保证了安全,但是牺牲了性能/效率

局部的锁对象,锁不住的.

互斥锁原理

原子属性

原子属性 : 单写多度,单个线程写入,多个线程可以读取

原理 : setter方法内部加了一把自旋锁,自旋锁看不见.

IOS开发建议:所有属性都声明为nonatomic

nonatomic和atomic对比

->atomic:线程安全,需要消耗大量的资源

->nonatomic:非线程安全,适合内存小得移动设备


互斥锁和自旋锁

weak和strong

OC对象用strong修饰

UI控件用weak修饰,当这个UI控件作为跟视图的时候,用strong修饰

IOS中的内存管理

自动释放池

自动释放池关键问题

什么时候使用自动释放池?

如果在循环中创建了大量的临时变量的时候需要在循环一开始就手动创建一个自动释放池

注:如果你生成了一个子线程的时候,要在线程开始执行的时候,尽量创建一个自动释放池,否则会内存泄露.因为子线程无法访问主线程的自动释放池

消息循环的作用

1. 保证应用程序不退出

2. 循环的检测事件,并且执行事件对应的方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值