)ios多線程開發——NSOperation詳解

來源:互聯網
上載者:User

多線程開發是一件需要特別精心的事情,即使是對有多年開發經驗的工程師來說。

為了能讓初級開發工程師也能使用多線程,同時還要簡化複雜性。各種編程工具提供了各自的辦法。對於iOS來說,建議在儘可能的情況下避免直接操作線程,使用比如NSOperationQueue這樣的機制。

可以把NSOperationQueue看作一個線程池,可往線程池中添加操作(NSOperation)到隊列中。線程池中的線程可看作消費者,從隊列中取走操作,並執行它。

你可以設定線程池中只有一個線程,這樣,各個操作就可以認為是近似的順序執行了。為什麼說是近似呢,後面會做解釋。

 

編寫最簡單的樣本

先寫個最簡單的樣本。

 

編寫一個NSOperation的子類,只需實現main方法。這裡非常類似Java的Thread,你可以繼承它,並覆蓋run方法,在該方法裡面寫入需要執行的代碼。這裡的main方法和run方法作用是相似的。

標頭檔:

@interface MyTask : NSOperation { 
    int operationId; 
}

@property int operationId;

@end

這裡的operationId屬性不是必須的,是我想在後面標識區分多個Task的標識位。

m檔案:

@implementation MyTask

@synthesize operationId;

- (void)main{ 
    NSLog(@"task %i run … ",operationId); 
    [NSThread sleepForTimeInterval:10]; 
    NSLog(@"task %i is finished. ",operationId); 
}

@end

這裡類比了一個耗時10秒鐘的操作。

下面需要把Task加入到隊列中:

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    queue=[[NSOperationQueue alloc] init]; 
    
    int index=1; 
    MyTask *task=[[[MyTask alloc] init] autorelease]; 
    task.operationId=index++; 
         
    [queue addOperation:task];

我直接找了個Controller的方法寫上了。運行結果是,介面出現了,而task還未執行完,說明是多線程的。10秒鐘後,日誌列印完畢,類似這樣:

2011-07-18 15:59:14.622 MultiThreadTest[24271:6103] task 1 run … 
2011-07-18 15:59:24.623 MultiThreadTest[24271:6103] task 1 is finished.

可以向操作隊列(NSOperationQueue)增加多個操作,比如這樣:

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    queue=[[NSOperationQueue alloc] init]; 
    
    int index=1; 
    MyTask *task=[[[MyTask alloc] init] autorelease]; 
    task.operationId=index++;     
    [queue addOperation:task]; 
    
    task=[[[MyTask alloc] init] autorelease]; 
    task.operationId=index++;

    [queue addOperation:task]; 
}

 

那麼列印出的內容是不定的,有可能是這樣:

2011-07-18 15:49:48.087 MultiThreadTest[24139:6203] task 1 run … 
2011-07-18 15:49:48.087 MultiThreadTest[24139:1903] task 2 run … 
2011-07-18 15:49:58.122 MultiThreadTest[24139:6203] task 1 is finished. 
2011-07-18 15:49:58.122 MultiThreadTest[24139:1903] task 2 is finished.

甚至有可能是這樣:

2011-07-18 15:52:24.686 MultiThreadTest[24168:1b03] task 2 run … 
2011-07-18 15:52:24.685 MultiThreadTest[24168:6003] task 1 run … 
2011-07-18 15:52:34.708 MultiThreadTest[24168:1b03] task 2 is finished. 
2011-07-18 15:52:34.708 MultiThreadTest[24168:6003] task 1 is finished.

 

因為兩個操作提交的時間間隔很近,線程池中的線程,誰先啟動是不定的。

那麼,如果需要嚴格意義的順序執行,怎麼辦呢?

 

處理操作之間的依賴關係

如果操作直接有依賴關係,比如第二個操作必須等第一個操作結束後再執行,需要這樣寫:

queue=[[NSOperationQueue alloc] init];

int index=1; 
MyTask *task=[[[MyTask alloc] init] autorelease]; 
task.operationId=index++;

[queue addOperation:task];

task=[[[MyTask alloc] init] autorelease]; 
task.operationId=index++;

if ([[queue operations] count]>0) { 
    MyTask *theBeforeTask=[[queue operations] lastObject]; 
    [task addDependency:theBeforeTask]; 
}

[queue addOperation:task];

 

這樣,即使是多線程情況下,可以看到操作是嚴格按照先後次序執行的。

 

控制線程池中的線程數

可以通過類似下面的代碼:

[queue setMaxConcurrentOperationCount:2];

來設定線程池中的線程數,也就是並行作業數。預設情況下是-1,也就是沒有限制,同時運行隊列中的全部操作。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.