1. 程式人生 > >iOS 多執行緒初步研究-NSThread

iOS 多執行緒初步研究-NSThread

對於多執行緒的開發,iOS系統提供了多種不同的介面,先談談iOS多執行緒最基礎方面的使用。產生執行緒的方式姑且分兩類,一類是顯式呼叫,另一類是隱式呼叫。

一、顯示呼叫的類為NSThread。一般構造NSThread的執行緒物件可通過兩種方式:

1. 初始化執行緒主方法:

[NSThread detachNewThreadSelector:@selector(run:) toTarget:target withObject:obj];//類方法

NSThread *newThread = [[NSThread alloc] initWithTarget:target selector:@selector(run:) object:obj];

 //例項方法可以拿到執行緒物件,便於以後終止執行緒。

2. 定義NSThread的子類MyThread,然後實現main方法(即方法1中的run)。然後建立新物件:

MyThread *newThread = [[MyThread alloc] init];

啟動執行緒:[newThread start];

終止執行緒:實際上沒有真正提供終止執行緒的api,但有個方法可以方便地利用cancel方法; 它是改變執行緒執行的一個狀態標誌,我們可以這樣來利用:

先在run:或main方法中這樣實現執行緒迴圈:

- (void)main

{

    // thread init

    while

 (![[NSThread currentThreadisCancelled])

    {

        // thread loop

        [NSThread sleepForTimeInterval:1.0]; //等同於sleep(1);

    }

    // release resources of thread

}

 這時如果呼叫[newThread cancel]; 就可以終止執行緒迴圈了。

 NSThread有個類方法exit是用於立即結束當前執行緒的執行(有點魯莽),因為無法保證當前執行緒對資源的釋放,所以不推薦使用。

二、隱式呼叫

通過NSObject的Category方法呼叫,羅列如下:

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; //在主執行緒中執行方法,wait表示是否阻塞這個方法的呼叫,如果為YES則等待主執行緒中執行方法結束。一般可用於在子執行緒中呼叫UI方法。

- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait; //在指定執行緒中執行,但該執行緒必須具備run loop。

- (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg; //隱含產生新執行緒。


三、NSThread的其它一些常用的方法

建立的執行緒是非關聯執行緒(detached thread),即父執行緒和子執行緒沒有執行依賴關係,父執行緒結束並不意味子執行緒結束。

1. + (NSThread *)currentThread; //獲得當前執行緒

2. + (void)sleepForTimeInterval:(NSTimeInterval)ti; //執行緒休眠

3. + (NSThread *)mainThread; //主執行緒,亦即UI執行緒了

4. - (BOOL)isMainThread; + (BOOL)isMainThread; //當前執行緒是否主執行緒

5. - (BOOL)isExecuting; //執行緒是否正在執行

6. - (BOOL)isFinished; //執行緒是否已結束

四、一些非執行緒呼叫(NSObject的Category方法)

即在當前執行緒執行,注意它們會阻塞當前執行緒(包括UI執行緒):

- (id)performSelector:(SEL)aSelector;

- (id)performSelector:(SEL)aSelector withObject:(id)object;

- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

 以下呼叫在當前執行緒延遲執行,如果當前執行緒沒有顯式使用NSRunLoop或已退出就無法執行了,需要注意這點:

- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray *)modes;

- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;

而且它們可以被終止:

+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget selector:(SEL)aSelector object:(id)anArgument;

+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget;

五、執行緒執行順序

通常UI需要顯示網路資料時,可以簡單地利用執行緒的執行順序,避免顯式的執行緒同步:

1. UI執行緒呼叫

[threadObjperformSelectorInBackground:@selector(loadData) withObject:nil];

2. 子執行緒中回撥UI執行緒來更新UI

- (void)loadData

{

    //query data from network

    //update data model

    //callback UI thread

    [uiObj performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:YES];

}

也可以使用NSThread實現同樣的功能,loadData相當於NSThread的main方法。