iOS多執行緒之Pthread/NSthread

NO IMAGE

多執行緒基礎知識


程序

程序是指在系統中正在運⾏行的一個應用程式 
每個程序之間是獨⽴的,每個程序均運⾏在其專用且受保護的記憶體空間內 

執行緒

一個程序要想執⾏任務,必須得有執行緒(每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 都不是執行緒安全的!”考慮到效率,只能這樣取捨”

日常開發中,使用鎖的機會很少,多執行緒的目的,就是將耗時的操作放在後臺!