iOS多線程的初步研究(一)-- NSThread

iOS多線程的初步研究(一)-- NSThread

對於多線程的開發,iOS系統提供了多種不一樣的接口,先談談iOS多線程最基礎方面的使用。產生線程的方式姑且分兩類,一類是顯式調用,另外一類是隱式調用。html

1、顯示調用的類爲NSThread。通常構造NSThread的線程對象可經過兩種方式:java

1. 初始化線程主方法:api

[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)。而後建立新對象:oop

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

啓動線程:[newThread start];ui

終止線程:實際上沒有真正提供終止線程的api,但有個cancel方法能夠利用; 它改變線程運行的一個狀態標誌,咱們能夠這樣來利用:url

先在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是用於當即結束當前線程的運行(不安全),由於沒法保證當前線程對資源的釋放,因此不推薦使用。像java中Thread的stop方法也被棄用同樣,由於不安全。

 

2、隱式調用

經過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; //隱含產生新線程。


3、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; //線程是否已結束

 

4、一些非線程調用(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;

 

5、線程執行順序

一般UI須要顯示網絡數據時,能夠簡單地利用線程的執行順序,避免顯式的線程同步:

1. UI線程調用

[threadObj performSelectorInBackground:@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方法。

相關文章
相關標籤/搜索