最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

在IOS中為什么使用多線程及多線程實現(xiàn)的三種方法

 更新時間:2015年11月23日 15:38:36   投稿:mrr  
這篇文章給大家介紹在IOS中為什么使用多線程及多線程實現(xiàn)的三種方法,基本上使用這三種方法實現(xiàn)多線程(NSThread Grand Centeral Dispatch(GCD) NSOperation和NSOperationQueue),感興趣的朋友可以參考下本篇文章

多線程是一個比較輕量級的方法來實現(xiàn)單個應(yīng)用程序內(nèi)多個代碼執(zhí)行路徑。

在系統(tǒng)級別內(nèi),程序并排執(zhí)行,程序分配到每個程序的執(zhí)行時間是基于該程序的所需時間和其他程序的所需時間來決定的。

然而,在每個程序內(nèi)部,存在一個或者多個執(zhí)行線程,它同時或在一個幾乎同時發(fā)生的方式里執(zhí)行不同的任務(wù)。

概要提示:

iPhone中的線程應(yīng)用并不是無節(jié)制的,官方給出的資料顯示,iPhone OS下的主線程的堆棧大小是1M,第二個線程開始就是512KB,并且該值不能通過編譯器開關(guān)或線程API函數(shù)來更改,只有主線程有直接修改UI的能力

一、線程概述

有些程序是一條直線,起點到終點——如簡單的hello world,運行打印完,它的生命周期便結(jié)束了,像是曇花一現(xiàn)。

有些程序是一個圓,不斷循環(huán)直到將它切斷——如操作系統(tǒng),一直運行直到你關(guān)機(jī)。

一個運行著的程序就是一個進(jìn)程或者叫做一個任務(wù),一個進(jìn)程至少包含一個線程,線程就是程序的執(zhí)行流。

Mac和IOS中的程序啟動,創(chuàng)建好一個進(jìn)程的同時,一個線程便開始運作,這個線程叫做主線程。主線成在程序中的位置和其他線程不同,它是其他線程最終的父線程,且所有的界面的顯示操作即AppKit或UIKit的操作必須在主線程進(jìn)行。

系統(tǒng)中每一個進(jìn)程都有自己獨立的虛擬內(nèi)存空間,而同一個進(jìn)程中的多個線程則公用進(jìn)程的內(nèi)存空間。

每創(chuàng)建一個新的進(jìn)成,都需要一些內(nèi)存(如每個線程有自己的stack空間)和消耗一定的CPU時間。

當(dāng)多個進(jìn)成對同一個資源出現(xiàn)爭奪的時候需要注意線程安全問題

創(chuàng)建線程

創(chuàng)建一個新的線程就是給進(jìn)程增加一個執(zhí)行流,所以新建一個線程需要提供一個函數(shù)或者方法作為線程的進(jìn)口。

1.使用NSThread

NSThread提供了創(chuàng)建線程的路徑,還可以提供了監(jiān)測當(dāng)前線程是否是主線程的方法使用NSThread創(chuàng)建一個新的線程有兩種方式:

1.創(chuàng)建一個NSThread的對象,調(diào)用Start方法——使用一個目標(biāo)對象的方法初始化一個NSThread對象,或者創(chuàng)建一個繼承自NSThread的子類,實現(xiàn)起main方法?,然后在直接創(chuàng)建這個子類的對象。

2.使用detachNewThreadSelector:toTarget:withObject:這個類方法創(chuàng)建一個子線程,這個比較直接,直接使用目標(biāo)對象的方法作為線程啟動入口

2.使用NSObject

使用NSObject直接就加入了對多線程的支持,允許對象的某個方法在后臺運行。

[my0bj performSelectorInBackground:@selector(doSomething) withObject:nil];

3.POSIX Thread

由于Mac和IOS都是基于Darwin系統(tǒng),Darwin系統(tǒng)的UNX內(nèi)核,是基于mach和BSD的,繼承了BSD的POSIX接口,所以可以直接使用POSIX線程的相關(guān)接口開實現(xiàn)線程
創(chuàng)建線程的接口為 pthread_create, 當(dāng)然在創(chuàng)建線程之前可以創(chuàng)建好相關(guān)線程的屬性

——————————————————————————————————————

NSOperation&NSOperationQueue

很多時候我們使用多線程,需要控制線程的并發(fā)數(shù),畢竟線程也是需要消耗系統(tǒng)資源的,當(dāng)程序中同時運行的線程過多時,系統(tǒng)必然變慢,所以很多時候我們會控制同時運行線程的數(shù)目
NSOperation可以封裝我們的操作,然后將創(chuàng)建好的NSOperation對象放到NSOperationQueue隊列中,OperationQueue便開始啟動新的線程去執(zhí)行隊列中的操作,OperationQueue的并發(fā)數(shù)時可以通過如下方式進(jìn)行設(shè)置的:

- (void)setMaxConcurrentOperationCount:(NSInteger)count

GCD時Grand central Dispatch的縮寫,是一系列BSD層面的接口。在mac10.6和IOS4.0以后才引入的且現(xiàn)在NSOperation和NSOperationQueue的多線程的實現(xiàn)就是基于GCD的。目前這個特性也被移植到 FreeBSD上了,可以查看libdispatch這個開源項目。

dispatch_queue_t imageDownloadQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

當(dāng)然,GCD除了處理多線程外還有很多非常好的功能,其建立在強大的kqueue之上,效率也能夠得到保障。

前言

在多線程簡介中,我已經(jīng)說明過了,為了提高界面的流暢度以及用戶體驗。我們務(wù)必要把耗時的操作放到別的線程中去執(zhí)行,千萬不要阻塞主線程。

下面小編給大家?guī)砣Nios多線程編程方法:

NSThread
Grand Centeral Dispatch(GCD)
NSOperation和NSOperationQueue

1.NSThread

這是最輕量級的多線程的方法,使用起來最直觀的多線程編程方法。但是因為需要自己管理線程的生命周期,線程同步。經(jīng)常使用NSThread進(jìn)行調(diào)試,在實際項目中不推薦使用。

//獲取當(dāng)前線程
NSThread *current = [NSThread currentThread];
//獲取主線程
NSThread *main = [NSThread mainThread];
NSLog(@"當(dāng)前線程 --- %@",current);
NSLog(@"主線程 --- %@",main);

控制臺輸出結(jié)果:

2015-11-22 22:30:29.572 多線程demo[1289:2925847] 當(dāng)前線程 --- <NSThread: 0x7fc0e1401dc0>{number = 1, name = main}
2015-11-22 22:30:29.572 多線程demo[1289:2925847] 主線程 --- <NSThread: 0x7fc0e1401dc0>{number = 1, name = main}

從結(jié)果我們看出當(dāng)前的線程就是主線程, number 相當(dāng)于線程的id, name 是線程的名稱,主線程的number就是1

阻塞線程:

//阻塞線程3秒
[NSThread sleepForTimeInterval:3];
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:3]];

2.GCD(Grand Central Dispatch)

GCD是基于C語言底層API實現(xiàn)的一套多線程并發(fā)機(jī)制,非常的靈活方便,在實際的開發(fā)中使用很廣泛。

簡單來說CGD就是把 操作 放在 隊列 中去執(zhí)行。

你只需定義好操作和隊列就可以了,不需要直接控制線程的創(chuàng)建和銷毀,線程的生命周期由隊列來管理。

隊列:負(fù)責(zé)操作的調(diào)度和執(zhí)行,有先進(jìn)先出(FIFO)的特點。也就是說先加入隊列的操作先執(zhí)行,后加入的后執(zhí)行。

隊列有兩種:

串行隊列:

隊列中的操作只會按順序執(zhí)行,你可以想象成單窗口排隊。

并行隊列:

隊列中的操作可能會并發(fā)執(zhí)行,這取決與操作的類型,你可以想象成多窗口排隊。

//創(chuàng)建串行隊列
dispatch_queue_t q = dispatch_queue_create("my_serial_queue", DISPATCH_QUEUE_SERIAL);
//創(chuàng)建并行隊列
dispatch_queue_t q = dispatch_queue_create("my_concurrent_queue", DISPATCH_QUEUE_CONCURRENT);

my_serial_queue和my_concurrent_queue是隊列的名字標(biāo)簽,為了與其他的隊列區(qū)分,在一個項目里面必須是唯一的。

DISPATCH_QUEUE_SERIAL表示串行隊列

DISPATCH_QUEUE_CONCURRENT表示并行隊列

操作同樣也分兩種類型:

同步操作:只會按順序執(zhí)行,執(zhí)行順序是確定的。

異步操作:在串行隊列中執(zhí)行順序確定,在并行隊列中執(zhí)行順序不確定

使用block來定義操作要執(zhí)行的代碼,q是已經(jīng)定義好的,操作要加入的隊列

//定義同步操作
dispatch_sync(q, ^{
 //要執(zhí)行的代碼 
});
//定義異步操作
dispatch_async(q, ^{
 //要執(zhí)行的代碼  
});

下面我們看一下同步,異步操作加入到串行和并行隊列里面,執(zhí)行的順序和特點:1.同步操作不管加入到何種隊列,只會在主線程按順序執(zhí)行

dispatch_queue_t q_serial = dispatch_queue_create("my_serial_queue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t q_concurrent = dispatch_queue_create("my_concurrent_queue", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < 5; ++i) {
 dispatch_sync(q_serial, ^{
 NSLog(@"串行隊列里的同步任務(wù) %@ %d", [NSThread currentThread], i);
 });
}
for (int i = 0; i < 5; ++i) {
 dispatch_sync(q_concurrent, ^{
 NSLog(@"并行隊列里的同步任務(wù) %@ %d", [NSThread currentThread], i);
 });
}

下面是控制臺輸出結(jié)果:

2015-11-23 00:40:36.862 01.GCD演練[1952:3613752] 串行隊列里的同步任務(wù) <NSThread: 0x7ff833505450>{number = 1, name = main} 0
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 串行隊列里的同步任務(wù) <NSThread: 0x7ff833505450>{number = 1, name = main} 1
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 串行隊列里的同步任務(wù) <NSThread: 0x7ff833505450>{number = 1, name = main} 2
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 串行隊列里的同步任務(wù) <NSThread: 0x7ff833505450>{number = 1, name = main} 3
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 串行隊列里的同步任務(wù) <NSThread: 0x7ff833505450>{number = 1, name = main} 4
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 并行隊列里的同步任務(wù) <NSThread: 0x7ff833505450>{number = 1, name = main} 0
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 并行隊列里的同步任務(wù) <NSThread: 0x7ff833505450>{number = 1, name = main} 1
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 并行隊列里的同步任務(wù) <NSThread: 0x7ff833505450>{number = 1, name = main} 2
2015-11-23 00:40:36.864 01.GCD演練[1952:3613752] 并行隊列里的同步任務(wù) <NSThread: 0x7ff833505450>{number = 1, name = main} 3
2015-11-23 00:40:36.864 01.GCD演練[1952:3613752] 并行隊列里的同步任務(wù) <NSThread: 0x7ff833505450>{number = 1, name = main} 4

2.異步操作只在非主線程的線程執(zhí)行,在串行隊列中異步操作會在新建的線程中按順序執(zhí)行。

 dispatch_queue_t q_serial = dispatch_queue_create("my_serial_queue", DISPATCH_QUEUE_SERIAL);
 for(int i = 0; i < 5; ++i){
  dispatch_async(q_serial, ^{
   NSLog(@"串行隊列 -- 異步任務(wù) %@ %d", [NSThread currentThread], i);
  });
 }

因為是異步操作,所以會新建一個線程。又因為加入到串行隊列中,所以所有的操作只會按順序執(zhí)行。

2015-11-23 01:03:22.372 01.GCD演練[2081:3627139] 串行隊列 -- 異步任務(wù) <NSThread: 0x7fb593d42f50>{number = 2, name = (null)} 0
2015-11-23 01:03:23.373 01.GCD演練[2081:3627139] 串行隊列 -- 異步任務(wù) <NSThread: 0x7fb593d42f50>{number = 2, name = (null)} 1
2015-11-23 01:03:24.374 01.GCD演練[2081:3627139] 串行隊列 -- 異步任務(wù) <NSThread: 0x7fb593d42f50>{number = 2, name = (null)} 2
2015-11-23 01:03:25.375 01.GCD演練[2081:3627139] 串行隊列 -- 異步任務(wù) <NSThread: 0x7fb593d42f50>{number = 2, name = (null)} 3
2015-11-23 01:03:26.376 01.GCD演練[2081:3627139] 串行隊列 -- 異步任務(wù) <NSThread: 0x7fb593d42f50>{number = 2, name = (null)} 4

3.異步操作,并行隊列

 dispatch_queue_t q_concurrent = dispatch_queue_create("my_concurrent_queue", DISPATCH_QUEUE_CONCURRENT);
 for(int i = 0; i < 5; ++i){
  dispatch_async(q_concurrent, ^{
   NSLog(@"并行隊列 -- 異步任務(wù) %@ %d", [NSThread currentThread], i);
  });
 }

理論上并行隊列會給每一個異步操作新建線程,然后讓所有的任務(wù)并發(fā)執(zhí)行。但是實際上系統(tǒng)能創(chuàng)建的線程數(shù)量是有限的,當(dāng)創(chuàng)建的線程達(dá)到最大線程數(shù)以后,后面的異步操作就需要等待前面的操作執(zhí)行完畢才能得到執(zhí)行。哪個線程操作執(zhí)行完畢,就把等待的異步任務(wù)安排到哪個線程。直到所有的操作執(zhí)行完畢。你可以把上述代碼的循環(huán)次數(shù)改成5000就可以觀察到此現(xiàn)象。

2015-11-23 01:14:15.282 01.GCD演練[2165:3634728] 并行隊列 -- 異步任務(wù) <NSThread: 0x7fb3b841b0a0>{number = 4, name = (null)} 3
2015-11-23 01:14:15.282 01.GCD演練[2165:3634724] 并行隊列 -- 異步任務(wù) <NSThread: 0x7fb3b8514da0>{number = 3, name = (null)} 0
2015-11-23 01:14:15.282 01.GCD演練[2165:3634726] 并行隊列 -- 異步任務(wù) <NSThread: 0x7fb3b8604db0>{number = 5, name = (null)} 2
2015-11-23 01:14:15.282 01.GCD演練[2165:3634725] 并行隊列 -- 異步任務(wù) <NSThread: 0x7fb3b86119d0>{number = 2, name = (null)} 1
2015-11-23 01:14:15.285 01.GCD演練[2165:3634729] 并行隊列 -- 異步任務(wù) <NSThread: 0x7fb3b87011f0>{number = 6, name = (null)} 4

3.NSOperation & NSOperationQueue

雖然GCD的功能已經(jīng)很強大了,但是它使用的API依然是C語言的。在某些時候,在面向?qū)ο蟮膐bjective-c中使用起來非常的不方便和不安全。

所以蘋果公司把GCD中的操作抽象成NSOperation對象,把隊列抽象成NSOperationQueue對象。


抽象為NSOperation & NSOperationQueue以后的好處有一下幾點:

代碼風(fēng)格統(tǒng)一了,我們不用在面向?qū)ο蟮膐bjective-C中寫面對過程的C語言代碼了。
我們知道在GCD中操作的執(zhí)行代碼都是寫在匿名的block里面,那么我們很難做到給操作設(shè)置依賴關(guān)系以及取消操作。這些功能都已經(jīng)封裝到NSOperation對象里面了。^-^
NSOperationQueue對象比GCD中隊列更加的強大和靈活,比如:設(shè)置并發(fā)操作數(shù)量,取消隊列中所有操作。
NSOperation分為NSInvocationOperation和NSBlockOperation

NSInvocationOperation的使用

//首先定義一個NSOperationQueue對象
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationAction:) object:@"這里可以穿參數(shù)"];
[queue addOperation:op];//把操作加入隊列中即開始執(zhí)行
- (void)operationAction:(id)obj
{
 NSLog(@"%@ - obj : %@", [NSThread currentThread], obj);
}

輸出為:

2015-11-23 02:55:19.067 多線程demo[2604:3686934] <NSThread: 0x7f9dfa443510>{number = 2, name = (null)} - obj : 這里可以穿參數(shù)

NSBlockOperation的使用

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
 [self operationAction:@"這是NSBlockOperation"];
}];
[queue addOperation:op];

輸出為:

2015-11-23 02:56:11.812 多線程demo[2617:3687872] <NSThread: 0x7fa983f10a50>{number = 2, name = (null)} - obj : 這是NSBlockOperation

設(shè)置依賴關(guān)系(執(zhí)行順序)

 NSOperationQueue *queue = [[NSOperationQueue alloc] init];
 NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationAction:) object:@"op1"];
 NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationAction:) object:@"op2"];
 //op2在op1之后執(zhí)行
 [op2 addDependency:op1];//這里需要注意,一定要在addOperation之前設(shè)置依賴關(guān)系 
 [queue addOperation:op1];
 [queue addOperation:op2];

輸出為:

2015-11-23 02:57:40.283 多線程demo[2661:3689737] <NSThread: 0x7fb663e132d0>{number = 2, name = (null)} - obj : op1
2015-11-23 02:57:40.284 多線程demo[2661:3689737] <NSThread: 0x7fb663e132d0>{number = 2, name = (null)} - obj : op2

沒有設(shè)置依賴關(guān)系的輸出:

2015-11-23 03:00:45.939 多線程demo[2709:3692307] <NSThread: 0x7fe951d0d8a0>{number = 2, name = (null)} - obj : op2
2015-11-23 03:00:45.939 多線程demo[2709:3692308] <NSThread: 0x7fe951c24720>{number = 3, name = (null)} - obj : op1

到這里你應(yīng)該發(fā)現(xiàn)了,在NSOperation & NSOperationQueue中,我們不需要再像GCD那樣定義操作的類型和隊列的類型和控制操作的執(zhí)行順序了,你只需要直接設(shè)定操作的執(zhí)行順序就可以了。

相關(guān)文章

  • 實例講解iOS中的CATransition轉(zhuǎn)場動畫使用

    實例講解iOS中的CATransition轉(zhuǎn)場動畫使用

    CATransition類為應(yīng)用程序的轉(zhuǎn)場動畫提供了很多可控制參數(shù),接下來我們就以幾個實例講解iOS中的CATransition轉(zhuǎn)場動畫使用,需要的朋友可以參考下
    2016-06-06
  • IOS開發(fā)相冊圖片多選和刪除的功能

    IOS開發(fā)相冊圖片多選和刪除的功能

    之前小編有和大家分享過一篇關(guān)于從相冊選取單張照片的文章,那么下面這篇文章跟大家分享下如何相冊多圖選擇和刪除,以及包括拍照功能,有需要的可以參考學(xué)習(xí),下面來一起看看吧。
    2016-09-09
  • IOS 調(diào)整內(nèi)存中的圖片大小實例詳解

    IOS 調(diào)整內(nèi)存中的圖片大小實例詳解

    這篇文章主要介紹了IOS 調(diào)整內(nèi)存中的圖片大小實例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • IOS中UIWebView的使用詳解

    IOS中UIWebView的使用詳解

    這篇文章主要介紹了IOS中UIWebView的使用詳解,涉及到初始化與三種加載方式,一些常用的屬性和變量及ios7中的一些新特征,本文介紹的非常詳細(xì),感興趣的朋友一起學(xué)習(xí)吧
    2016-02-02
  • iOS開發(fā)實現(xiàn)圖片瀏覽功能

    iOS開發(fā)實現(xiàn)圖片瀏覽功能

    這篇文章主要為大家詳細(xì)介紹了iOS開發(fā)實現(xiàn)圖片瀏覽功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • iOS使用CoreMotion實現(xiàn)搖一搖功能

    iOS使用CoreMotion實現(xiàn)搖一搖功能

    這篇文章主要為大家詳細(xì)介紹了iOS使用CoreMotion實現(xiàn)搖一搖功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • iOS?StoreKit?2?新特性盤點解析

    iOS?StoreKit?2?新特性盤點解析

    這篇文章主要為大家介紹了iOS?StoreKit?2?新特性盤點及要點解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • iOS如何固定UITableView中cell.imageView.image的圖片大小

    iOS如何固定UITableView中cell.imageView.image的圖片大小

    這篇文章主要給大家介紹了關(guān)于iOS如何固定UITableView中cell.imageView.image圖片大小的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對各位iOS開發(fā)者們的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-11-11
  • iOS中的UIKeyboard鍵盤視圖使用方法小結(jié)

    iOS中的UIKeyboard鍵盤視圖使用方法小結(jié)

    鍵盤視圖我們平時在做App的時候都要調(diào)用得到,這里我們就來整理一下iOS中的UIKeyboard鍵盤視圖使用方法小結(jié),需要的朋友可以參考下
    2016-06-06
  • iOS利用UIBezierPath + CAAnimation實現(xiàn)路徑動畫效果

    iOS利用UIBezierPath + CAAnimation實現(xiàn)路徑動畫效果

    在iOS開發(fā)中,制作動畫效果是最讓開發(fā)者享受的環(huán)節(jié)之一,這篇文章主要給大家介紹了關(guān)于iOS利用UIBezierPath + CAAnimation實現(xiàn)路徑動畫效果的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-10-10

最新評論

抚顺县| 乌鲁木齐县| 城口县| 苍梧县| 错那县| 日土县| 柞水县| 苏尼特右旗| 米林县| 收藏| 太康县| 襄樊市| 茂名市| 工布江达县| 招远市| 衡东县| 肃北| 固原市| 石渠县| 林州市| 即墨市| 昌平区| 怀集县| 介休市| 杭州市| 德安县| 辰溪县| 汪清县| 焦作市| 门源| 上饶县| 博爱县| 安溪县| 盱眙县| 彭水| 浑源县| 巴林左旗| 尤溪县| 萍乡市| 喀喇| 文化|