iOS多线程之Pthread/NSthread

来源:互联网 发布:兼职在家做数据录入 编辑:程序博客网 时间:2024/04/30 09:18

多线程基础知识


进程

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

线程

一个进程要想执⾏任务,必须得有线程(每1个进程⾄少要有1条线程) 
线程是进程的基本执⾏单元,一个进程(程序)的所有任务都在线程中执⾏ 

  • 进程负责开辟内存空间
  • 线程负责执行任务

线程的串⾏(排排坐,吃果果,你一个,我一个) 
一个线程中任务的执⾏是串⾏(顺序执⾏)的 
如果要在一个线程中执⾏多个任务,那么只能⼀个⼀个地按顺序执⾏行这些任务  
也就是说,在同⼀时间内,一个线程只能执⾏一个任务 

多线程


一个进程中可以开启多条线程,每条线程可以并发(同时)执⾏不同的任务 
多线程技术可以提⾼高程序的执⾏行效率 

多线程的原理

同⼀时间,CPU只能处理一条线程,只有一条线程在⼯作(执⾏)。多线程并发(同时)执⾏,其实是CPU快速地在多条线程之间调度(切换), 如果CPU调度线程的时间⾜够快,就造成了多线程并发执⾏的假象。如果线程非常多,CPU会在N多线程之间调度,CPU会累死,消耗⼤大量的CPU资源。

多线程的优点

● 能适当提高程序的执行效率,开启新应用能立刻执行,不需要等之前的运行完毕。 
● 能适当提高资源利用率(CPU、内存利⽤用率) 

多线程的缺点

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

主线程


一个IOS程序运行后,默认会开启一条线程,称为“主线程”或者“UI”线程。 
主线程的作用:主要是显示和刷新UI界面,处理UI的操作事件 
主线程注意:不要将耗时的操作放到主线程中,因为耗时的会一直占用主线程,导致UI的滚动,拖拽,点击事件不能被处理,影响UI的流畅度,出现“卡顿”现象,导致用户体验不佳。所以一般将耗时操作放在子线程中进行

[NSThread currentThread] 
可以在所有的多线程技术中使用 
打印当前线程3

[NSThread currentThread] 
通常用来在多线程开发中,判断是否在主线程 
number == 1 说明是主线程 
number != 1 说明是其他线程


IOS多线程方案

实例化:pthread

<code class="language-object c hljs  has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 创建线程</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// C语言中类型的结尾通常 _t/Ref,而且不需要使用 *</span>    pthread_t threadId;    NSString *str = @<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Hello Pthread"</span>;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> result = pthread_create(&threadId, NULL, &demo, (__bridge <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> *)(str));    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 在其他线程执行  demo 函数  返回int类型的数值     参数     1. 线程代号的地址     2. 线程的属性     3. 调用函数的指针     4. 传递给该函数的参数     返回值     - 如果是0,表示正确     - 如果是非0,表示错误码     */</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (result == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {        NSLog(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"OK"</span>);    } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {        NSLog(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"error %d"</span>, result);    }}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> *demo(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> *param) {    NSString *sss = (__bridge NSString *)(param);    NSLog(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%@, %@"</span>, [NSThread currentThread], sss);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> NULL;}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li></ul>

void * 和 OC 中的 id 是等价的

id(*)(id)

  • 在 ARC 开发中,如果设计到和 C 语言中相同的数据类型进行转换时,需要使用 __bridge “桥接”
  • 在 MRC 开发中,不需要桥接

    在 OC 中,如果是 ARC 开发,编译器会在编译的时候,自动根据代码结构,添加 retain, release, autorelease 
    ARC 只负责 OC 部分的代码,不负责 C 的代码,如果 C 语言的框架出现 retain/create/copy 字样的函数,都需要release

    关于桥接的添加,可以利用 Xcode 辅助实现!

实例化:NSthread

主要语句:

<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 创建线程,运行demo方法</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>、<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> *thread = [[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> alloc] initWithTarget:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> selector:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@selector</span>(demo:) object:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Thread"</span>];    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 启动线程</span>    [thread start];<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>、[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> detachNewThreadSelector:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@selector</span>(demo:) toTarget:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> withObject:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Detach"</span>];<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>、[<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> performSelectorInBackground:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@selector</span>(demo:) withObject:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"background"</span>];<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@implementation</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ViewController</span></span>- (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)viewDidLoad {    [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span> viewDidLoad];}- (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {    [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> threadDemo3_1];}<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// NSThread 创建</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//=====================================================================</span>- (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)threadDemo3_1 {    Person *p = [[Person alloc] init];    [p performSelectorInBackground:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@selector</span>(loadData) withObject:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>];}<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//============================</span>- (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)threadDemo3 {    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 打印当前是在那个线程</span>    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"1--%@"</span>, [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> currentThread]);    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 是 NSObject 的一个分类方法,意味着所有的 NSObject 都可以使用此方法,在其他线程执行方法!</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 特点:没有thread字眼,一旦制定,就会立即在后台线程执行 selector 方法</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// performSelectorInBackground 隐式的多线程方法</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 这种方法,在使用的时候更加灵活!</span>    [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> performSelectorInBackground:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@selector</span>(demo:) withObject:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"background"</span>];    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"2--%@"</span>, [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> currentThread]);}<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//=====================================================================</span>- (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)threadDemo2 {    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1</span>    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"1--%@"</span>, [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> currentThread]);    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// detachNewThreadSelector 会立即在后台线程执行 selector 方法,不需要手动star</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// detach => 分离一个子线程执行 demo: 方法</span>    [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> detachNewThreadSelector:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@selector</span>(demo:) toTarget:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> withObject:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Detach"</span>];    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1/2?</span>    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"2--%@"</span>, [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> currentThread]);}<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//=====================================================================</span>- (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)threadDemo1 {    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"1-------"</span>);    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 实例化线程/加载 => alloc(分配内存) / init(初始化)</span>    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> *thread = [[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> alloc] initWithTarget:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> selector:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@selector</span>(demo:) object:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Thread"</span>];    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 启动线程</span>    [thread start];    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 在线程1  输出</span>    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"2------- %@"</span>, [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> currentThread]);}- (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)demo:(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">id</span>)obj {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i<<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>; i++) {        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%@ %@"</span>, [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> currentThread], obj);    }}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@end</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li></ul>

NSthread的属性

线程的名字:在大的商业项目中,通常希望程序崩溃的时候,能够获取到程序准确执行所在的线程! 
线程优先级:优先级只是保证 CPU 调度的可能性会高,一般不设置优先级

<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> *t1 = [[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> alloc] initWithTarget:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> selector:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@selector</span>(demo) object:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>];    t1<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.name</span> = @<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Thread A"</span>; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// name 在大得项目中,能够准确获取程序执行所在的线程</span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 优先级,是一个浮点数,从0~1.0,1.0表示优先级最高,默认优先级是0.5</span>    t1<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.threadPriority</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.1</span>;    [t1 start];</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

线程的状态

新建:NSThread *t = [[NSThread alloc] initWithTarget:self selector:@selector(threadStatus) object:nil];放在可调度线程池中

就绪:[t start];放在可调度线程池中

运行:NSThread *t = [[NSThread alloc] initWithTarget:self selector:@selector(threadStatus) object:nil];

阻塞(睡一会儿):[NSThread sleepForTimeInterval:2.0];从可调度线程池中移出

[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];  
从现在开始睡多久

死亡:[NSThread exit] 一般不要在主线程里面玩这个东东,在子线程中玩的时候,先做一个判断。exit之前要释放对象,因为Arc会清楚OC对象, 
但是C的对象要手动清除。

多线程的安全隐患

互斥锁 - 保证锁内的代码,同一时间,只有一条线程能够执行! 
利用互斥锁 防止把同一张车票卖给两个人

<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">- (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.tickets</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>;    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> *t1 = [[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> alloc] initWithTarget:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> selector:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@selector</span>(saleTickets) object:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>];    t1<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.name</span> = @<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"售票员 A"</span>;    [t1 start];    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> *t2 = [[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> alloc] initWithTarget:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span> selector:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@selector</span>(saleTickets) object:<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">nil</span>];    t2<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.name</span> = @<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"售票员 B"</span>;    [t2 start];}<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// MARK: - 卖票逻辑</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** 在开发多线程程序时,按照以下步骤 1. 保证单个线程执行正常! 2. 每一个售票逻辑(窗口)应该把所有的票卖完 3. 添加线程 */</span>- (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>)saleTickets {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> (<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">YES</span>) {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 模拟休眠</span>        [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> sleepForTimeInterval:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.0</span>];        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 注意,锁一定要是所有线程共享的对象,不能是对象里面的一个局部变量(上厕所自己兜里的锁)</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 如果代码中只有一个地方需要加锁,大多都使用 self</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 互斥锁 - 保证锁内的代码,同一时间,只有一条线程能够执行!</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 要锁住关键的操作,锁定范围越小,效率越高</span>        @synchronized(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>) { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// self就是加锁的对象,不能局部变量,能够加锁任意的NSObject对象</span>            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.tickets</span> > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.tickets</span>--;                <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"剩余票数 %d %@"</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.tickets</span>, [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> currentThread]);            } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {                <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSLog</span>(@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"没有票了 %@"</span>, [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSThread</span> currentThread]);                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>;            }        }    }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li></ul>

原子属性

  • nonatomic: 非原子属性(多线程,高效)
  • atomic: 原子属性(线程安全),就是针对多线程设计的,是默认属性 
    多个线程写入属性时,保证同一时间只有一个线程能够执行写入操作 
    单(线程)写多(线程)读的一种多线程技术,同样有可能出现“脏数据 (错误数据)”,重新读一下。

实际上,原子属性内部也有一把锁,自旋锁

自旋锁 & 互斥锁

  • 共同点 
    都能够保证同一时间,只有一条线程执行锁定范围的代码
  • 不同点

    • 互斥锁:如果发现有其他线程正在执行锁定的代码,线程会进入休眠状态,等待其他线程执行完毕,打开锁之后,线程会被唤醒
    • 自旋锁:如果发现有其他线程正在执行锁定的代码,线程会用死循环的方式,一直等待锁定代码执行完成!
  • 自旋锁更适合执行非常短的代码!无论什么锁,都是要付出代价的!多线程是追求效率,有锁安全,但是效率低

线程安全

在多个线程进行读写操作时,仍然能够保证数据正确!效率不高!

UI 线程,共同约定:所有更新 UI 的操作都在主线程上执行! 
原因:几乎所有的 UIKit 都不是线程安全的!”考虑到效率,只能这样取舍”

日常开发中,使用锁的机会很少,多线程的目的,就是将耗时的操作放在后台!

0 0