首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> C 語言入門

Objective-C 多執行緒建立兩大經典方法:initWithTarget 與 detachNewThreadSelector

     編輯:C 語言入門

方法一:NSThread initWithTarget:selector:object:

#import 

@interface Worker : NSObject
- (void)startTask:(NSString *)param;
@end

@implementation Worker
- (void)startTask:(NSString *)str {
    sleep(3); // 模擬耗時操作
    NSLog(@"Thread task: %@", str);
    // exit(0); // 注意:exit 會結束整個程序,實務不可用
}
@end

int main(int argc, const char *argv[]) {
    @autoreleasepool {
        NSLog(@"Main thread start");
    }
    
    Worker *worker = [[Worker alloc] init];
    NSThread *thread = [[NSThread alloc] initWithTarget:worker
                                             selector:@selector(startTask:)
                                               object:@"Start"];
    [thread start]; // 必須呼叫 start 啟動執行緒
    
    sleep(5); // 等待子執行緒完成
    return 0;
}

關鍵點

  • 建立 NSThread 實例後必須呼叫 start 才會真正啟動
  • object: 參數會作為 selector 唯一引數傳遞
  • 目標物件 (target) 由執行緒強持有 直到執行完成

方法二:NSThread detachNewThreadSelector:toTarget:withObject:

#import 

@interface Worker : NSObject
- (void)startTask:(NSString *)param;
@end

@implementation Worker
- (void)startTask:(NSString *)str {
    NSLog(@"Detached thread: %@", str);
    // exit(0); // 同樣不可用
}
@end

int main(int argc, const char *argv[]) {
    @autoreleasepool {
        NSLog(@"Main thread start");
        
        Worker *worker = [[Worker alloc] init];
        [NSThread detachNewThreadSelector:@selector(startTask:)
                                 toTarget:worker
                               withObject:@"Start"];
        // 無需手動 start,立即在新執行緒非同步執行
    }
    sleep(5);
    return 0;
}

關鍵差異

特性initWithTarget...detachNewThreadSelector...
啟動控制手動 [thread start]立即非同步啟動
執行緒物件可取得 NSThread* 控制無法取得執行緒物件參考
優先級設定啟動前可設 thread.qualityOfService無法預先設定
取消支援可呼叫 [thread cancel]不可直接取消
適用場景需精細控制執行緒生命週期簡單一次性背景任務

現代最佳實踐:GCD 與 Operation Queue

注意:上述兩種為傳統手動執行緒管理 (OS X 10.5 / iOS 2.0 時代)。現代開發 (iOS 4+ / OS X 10.6+) 強烈建議使用:

Grand Central Dispatch (GCD)

// 全域佇列 (背景執行緒)
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{
    NSLog(@"GCD Background: %@", @"Task");
    // 回主執行緒更新 UI
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"Back to Main Thread");
    });
});

// 自訂序列佇列 (串行執行)
dispatch_queue_t serialQueue = dispatch_queue_create("com.app.serial", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{ /* Task 1 */ });
dispatch_async(serialQueue, ^{ /* Task 2 等待 Task 1 完成 */ });

Operation / OperationQueue

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 2;

NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"Operation Task");
}];
op.completionBlock = ^{ NSLog(@"Completed"); };
[queue addOperation:op];

// 依賴關係
[op2 addDependency:op1]; // op2 等待 op1 完成

傳統 NSThread 仍需注意的場景

  1. RunLoop 需求:需在背景執行緒跑 RunLoop (如 NSTimer, 網路串流、Port 通訊)
  2. 執行緒區域儲存:[[NSThread currentThread] threadDictionary]
  3. 相容舊代碼庫:未遷移至 GCD 的專案維護

記憶體管理關鍵

  • @autoreleasepool:子執行緒入口處必須建立,避免記憶體洩漏
  • 物件跨執行緒傳遞:確保執行緒安全或使用不可變物件
  • UI 更新必須回主執行緒:dispatch_async(dispatch_get_main_queue(), ...)

結語

雖然 initWithTarget 與 detachNewThreadSelector 是 Objective-C 多執行緒的經典入門,但現代 iOS/macOS 開發首選 GCD 與 OperationQueue。理解傳統 API 有助於維護舊代碼、處理 RunLoop 等特殊場景,但新專案請直接採用現代併發框架,獲得更佳的效能、安全性與可維護性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved