要学习多线程的知识首先要了解一些多线程的基本知识,什么是线程,进程,多线程原理,多线程优缺点等。下面是多线程的基础知识
多线程基础知识
进程
进程是指在系统中正在运⾏行的一个应用程序
每个进程之间是独⽴的,每个进程均运⾏在其专用且受保护的内存空间内
线程
一个进程要想执⾏任务,必须得有线程(每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 都不是线程安全的!”考虑到效率,只能这样取舍”
日常开发中,使用锁的机会很少,多线程的目的,就是将耗时的操作放在后台!