iOS NSOperation 非并发执行
生活随笔
收集整理的這篇文章主要介紹了
iOS NSOperation 非并发执行
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
NSOperation提供了一種面向?qū)ο蟮姆椒▉矸庋b任務(wù)。NSOperation可以單獨執(zhí)行,也可以放到NSOperationQueue中執(zhí)行。 NSOperation是虛基類不能直接使用,但Cocoa提供了兩個簡單的子類NSBlockOperation和NSInvocationOperation。NSBlockOperation是將任務(wù)封裝到block對象中,NSInvocationOperation 是將任務(wù)封裝到selector。 NSBlockOperation 直接使用 - (void)startOperation
{
??? NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"NSBlockOperation Test"); }]; [operation start]; } 調(diào)用start方法開始執(zhí)行任務(wù),NSOperation的實例方法cancel可以取消正在執(zhí)行的任務(wù),這比GCD有優(yōu)勢(GCD中不提供取消任務(wù)的功能)。但是這里并不是我們想像的這么簡單調(diào)用一個cancel方法就夠了,看下面代碼: - (void)startOperation
{
??? NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
??????? while (1) {
??????????? NSLog(@"Test operation cancel funcation");
??????? } }]; [operation start]; [operation cancel]; } start方法調(diào)用后while循環(huán)會一直執(zhí)行,之后調(diào)用cancel方法,while循環(huán)會停止嗎?答案是不會的,因為cancel方法就不會被執(zhí)行,當(dāng)前線程一直卡在block任務(wù)中。 你可能會想我在start方法前設(shè)置0.01s延遲后調(diào)用實例的cancel方法呢?看下面代碼: - (void)startOperation
{
??? NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
??????? while (1) {
??????????? NSLog(@"Test operation cancel funcation");
??????? }
??? }]; self.operation = operation; [self performSelector:@selector(cancelOperation) withObject:nil afterDelay:0.01f]; [operation start]; } - (void)cancelOperation
{
??? [self.operation cancel]; } 實際運行發(fā)現(xiàn)cancelOperation方法根本就不會調(diào)用,這是為什么呢? NSOperation本身并不提供多線程的能力,任務(wù)是在當(dāng)前線程中異步執(zhí)行,任務(wù)執(zhí)行完成后才執(zhí)行后面的代碼。cancel方法寫在當(dāng)前線程,而當(dāng)前線程一直卡在while循環(huán)里,所以cancel方法根本就不會被調(diào)用。 既然在同一線程中不能取消死循環(huán)的任務(wù),那么,將任務(wù)放到后臺,在主線程中取消呢?NSOperationQueue提供多線程的能力,將NSOperation任務(wù)放到queue中執(zhí)行。看下面代碼: - (void)startOperation
{
??? NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
??????? while (1) {
??????????? NSLog(@"Test operation cancel funcation");
??????? }
??? }];
??? self.operation = operation;
??? NSOperationQueue *queue = [[NSOperationQueue alloc] init];
??? [queue addOperation:operation];
//??? [operation cancel];?
???
??? [self performSelector:@selector(cancelOperation) withObject:nil afterDelay:0.01f]; } 這里的cancelOperation方法和上面一樣省略了,operation任務(wù)被添加到NSOperationQueue中在下一個Runloop會被執(zhí)行,如果緊跟添加后取消,任務(wù)就不會被執(zhí)行。所以我們放到延遲方法中取消operation。這樣總能退出while循環(huán)了吧!測試發(fā)現(xiàn)while循環(huán)依然在執(zhí)行,這又是什么原因了? 在蘋果官方文檔上講解NSOperation有這么一段話: If an operation were terminated outright, there might not be a way to reclaim resources that had been allocated. As a result, operation objects are expected to check for cancellation events and to exit gracefully when they occur in the middle of the operation. 大致意思是任務(wù)被中斷了,但分配的內(nèi)存資源有可能回收不了,所以在執(zhí)行任務(wù)前要檢查任務(wù)是否被取消了。還有保證任務(wù)被取消后釋放分配的內(nèi)存,這點在后面的實現(xiàn)NSOperation子類中要特別注意。 下面這樣才是正確的 - (void)startOperation
{
??? __weak ViewController *wself = self;
???
??? NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
??????? while (wself.operation.isCancelled == NO) {
??????????? NSLog(@"Test operation cancel funcation");
??????? }
??? }];
??? self.operation = operation;
??? NSOperationQueue *queue = [[NSOperationQueue alloc] init];
??? [queue addOperation:operation]; [self performSelector:@selector(cancelOperation) withObject:nil afterDelay:0.01f]; } 上面使用的都是系統(tǒng)提供的NSOperation的子類,我們也可以自己定義新的子類。NSOperation的任務(wù)默認(rèn)是非并發(fā)執(zhí)行的,只讀屬性 BOOL concurrent(iOS7之后使用 BOOL asynchronous)默認(rèn)返回NO。 將NSOperationQueue之前先弄明白幾個概念:線程、同步、異步、并發(fā) 線程是程序執(zhí)行的最小單元,是進程中的一個實體,是被系統(tǒng)獨立調(diào)度和分派的基本單位,同一進程中的多個線程可以并發(fā)執(zhí)行。 線程同步是多個線程發(fā)生競爭資源,需要依次訪問,線程異步是多個線程可以同時對同一資源進行訪問 執(zhí)行同步是等待任務(wù)完成才能執(zhí)行后面的代碼,執(zhí)行異步是異步調(diào)用發(fā)出后,接著執(zhí)行后面的代碼,實際執(zhí)行調(diào)用的過程在后面完成,像performSelector調(diào)用。 并發(fā)執(zhí)行是指不需要等待任務(wù)執(zhí)行完也能執(zhí)行后面的代碼。 上面我用到了NSOperationQueue,處于cocoa最上層處理多線程隊列。NSOperationQueue會給加入的每個NSOperation任務(wù)開啟一個新的線程,當(dāng)任務(wù)執(zhí)行完成后銷毀其線程。多個任務(wù)是異步執(zhí)行的,既為異步隊列。但可以設(shè)置NSOperationQueue的最大同時執(zhí)行的任務(wù)數(shù)為1(maxConcurrentOperationCount = 1)來實現(xiàn)同步隊列。非并發(fā)的任務(wù)添加到NSOperationQueue隊列中也實現(xiàn)了異步執(zhí)行。因此如果你需要將NSOperation任務(wù)添加到NSOperationQueue隊列中,那就不需要實現(xiàn)NSOperation的并發(fā)任務(wù)。 關(guān)于自定義NSOperation子類和實現(xiàn)concurrent任務(wù)會在下一節(jié)講。
{
??? NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"NSBlockOperation Test"); }]; [operation start]; } 調(diào)用start方法開始執(zhí)行任務(wù),NSOperation的實例方法cancel可以取消正在執(zhí)行的任務(wù),這比GCD有優(yōu)勢(GCD中不提供取消任務(wù)的功能)。但是這里并不是我們想像的這么簡單調(diào)用一個cancel方法就夠了,看下面代碼: - (void)startOperation
{
??? NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
??????? while (1) {
??????????? NSLog(@"Test operation cancel funcation");
??????? } }]; [operation start]; [operation cancel]; } start方法調(diào)用后while循環(huán)會一直執(zhí)行,之后調(diào)用cancel方法,while循環(huán)會停止嗎?答案是不會的,因為cancel方法就不會被執(zhí)行,當(dāng)前線程一直卡在block任務(wù)中。 你可能會想我在start方法前設(shè)置0.01s延遲后調(diào)用實例的cancel方法呢?看下面代碼: - (void)startOperation
{
??? NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
??????? while (1) {
??????????? NSLog(@"Test operation cancel funcation");
??????? }
??? }]; self.operation = operation; [self performSelector:@selector(cancelOperation) withObject:nil afterDelay:0.01f]; [operation start]; } - (void)cancelOperation
{
??? [self.operation cancel]; } 實際運行發(fā)現(xiàn)cancelOperation方法根本就不會調(diào)用,這是為什么呢? NSOperation本身并不提供多線程的能力,任務(wù)是在當(dāng)前線程中異步執(zhí)行,任務(wù)執(zhí)行完成后才執(zhí)行后面的代碼。cancel方法寫在當(dāng)前線程,而當(dāng)前線程一直卡在while循環(huán)里,所以cancel方法根本就不會被調(diào)用。 既然在同一線程中不能取消死循環(huán)的任務(wù),那么,將任務(wù)放到后臺,在主線程中取消呢?NSOperationQueue提供多線程的能力,將NSOperation任務(wù)放到queue中執(zhí)行。看下面代碼: - (void)startOperation
{
??? NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
??????? while (1) {
??????????? NSLog(@"Test operation cancel funcation");
??????? }
??? }];
??? self.operation = operation;
??? NSOperationQueue *queue = [[NSOperationQueue alloc] init];
??? [queue addOperation:operation];
//??? [operation cancel];?
???
??? [self performSelector:@selector(cancelOperation) withObject:nil afterDelay:0.01f]; } 這里的cancelOperation方法和上面一樣省略了,operation任務(wù)被添加到NSOperationQueue中在下一個Runloop會被執(zhí)行,如果緊跟添加后取消,任務(wù)就不會被執(zhí)行。所以我們放到延遲方法中取消operation。這樣總能退出while循環(huán)了吧!測試發(fā)現(xiàn)while循環(huán)依然在執(zhí)行,這又是什么原因了? 在蘋果官方文檔上講解NSOperation有這么一段話: If an operation were terminated outright, there might not be a way to reclaim resources that had been allocated. As a result, operation objects are expected to check for cancellation events and to exit gracefully when they occur in the middle of the operation. 大致意思是任務(wù)被中斷了,但分配的內(nèi)存資源有可能回收不了,所以在執(zhí)行任務(wù)前要檢查任務(wù)是否被取消了。還有保證任務(wù)被取消后釋放分配的內(nèi)存,這點在后面的實現(xiàn)NSOperation子類中要特別注意。 下面這樣才是正確的 - (void)startOperation
{
??? __weak ViewController *wself = self;
???
??? NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
??????? while (wself.operation.isCancelled == NO) {
??????????? NSLog(@"Test operation cancel funcation");
??????? }
??? }];
??? self.operation = operation;
??? NSOperationQueue *queue = [[NSOperationQueue alloc] init];
??? [queue addOperation:operation]; [self performSelector:@selector(cancelOperation) withObject:nil afterDelay:0.01f]; } 上面使用的都是系統(tǒng)提供的NSOperation的子類,我們也可以自己定義新的子類。NSOperation的任務(wù)默認(rèn)是非并發(fā)執(zhí)行的,只讀屬性 BOOL concurrent(iOS7之后使用 BOOL asynchronous)默認(rèn)返回NO。 將NSOperationQueue之前先弄明白幾個概念:線程、同步、異步、并發(fā) 線程是程序執(zhí)行的最小單元,是進程中的一個實體,是被系統(tǒng)獨立調(diào)度和分派的基本單位,同一進程中的多個線程可以并發(fā)執(zhí)行。 線程同步是多個線程發(fā)生競爭資源,需要依次訪問,線程異步是多個線程可以同時對同一資源進行訪問 執(zhí)行同步是等待任務(wù)完成才能執(zhí)行后面的代碼,執(zhí)行異步是異步調(diào)用發(fā)出后,接著執(zhí)行后面的代碼,實際執(zhí)行調(diào)用的過程在后面完成,像performSelector調(diào)用。 并發(fā)執(zhí)行是指不需要等待任務(wù)執(zhí)行完也能執(zhí)行后面的代碼。 上面我用到了NSOperationQueue,處于cocoa最上層處理多線程隊列。NSOperationQueue會給加入的每個NSOperation任務(wù)開啟一個新的線程,當(dāng)任務(wù)執(zhí)行完成后銷毀其線程。多個任務(wù)是異步執(zhí)行的,既為異步隊列。但可以設(shè)置NSOperationQueue的最大同時執(zhí)行的任務(wù)數(shù)為1(maxConcurrentOperationCount = 1)來實現(xiàn)同步隊列。非并發(fā)的任務(wù)添加到NSOperationQueue隊列中也實現(xiàn)了異步執(zhí)行。因此如果你需要將NSOperation任務(wù)添加到NSOperationQueue隊列中,那就不需要實現(xiàn)NSOperation的并發(fā)任務(wù)。 關(guān)于自定義NSOperation子類和實現(xiàn)concurrent任務(wù)會在下一節(jié)講。
轉(zhuǎn)載于:https://www.cnblogs.com/shuleihen/p/4368897.html
總結(jié)
以上是生活随笔為你收集整理的iOS NSOperation 非并发执行的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: netty5.0通过LineBasedF
- 下一篇: Windows Server 2008