1. 程式人生 > >iOS 開啟常駐執行緒

iOS 開啟常駐執行緒

iOS上開啟常駐執行緒,有幾個方式,我做了幾個測試。(關於什麼是常駐執行緒,不熟悉的同學自己腦補一下吧)

1 iOS系統支援POSIX執行緒模型,當然就可以使用POSIX那一套執行緒api來開啟常駐執行緒。

void thread_fucn(void* arg)
{
    while (1)
    {
        // doing work here ...
        
        sleep(1);
    }
}


2 iOS高層API NSThread,可以開啟一個執行緒,但是,開啟一個常駐執行緒,有幾個方式

- (void)onStart:(UIButton*)sender
{
    NSLog(@"start %@",self.navigationItem.title);
    [NSThread detachNewThreadSelector:@selector(onThread:) toTarget:self withObject:nil];
    
}

- (void)onThread:(id)sneder
{
    NSLog(@"run ...");
    self.workerThread_NS = [NSThread currentThread];
    [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(onCheckNSTask:) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] run];
    NSLog(@"over");
}
- (void)onCheckNSTask:(id)sender
{
    NSLog(@"checking ..");
}

或者如下
- (void)onStart:(UIButton*)sender
{
    NSLog(@"start %@",self.navigationItem.title);
    [NSThread detachNewThreadSelector:@selector(onThread:) toTarget:self withObject:nil];
    
}

- (void)onThread:(id)sneder
{
    self.workerThread_NS = [NSThread currentThread];
    // Should keep the runloop from exiting
    CFRunLoopSourceContext context = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
    CFRunLoopSourceRef source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
    
    BOOL runAlways = YES; // Introduced to cheat Static Analyzer
    while (runAlways) {
        
        CFRunLoopRun();
        
    }
    
    // Should never be called, but anyway
    CFRunLoopRemoveSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
    CFRelease(source);
}

3 iOS底層API GCD庫支援開啟新的dispatch_queue_t,這個是一個執行緒管理器,給其不同引數,開啟不同的執行緒模式:線性、併發模式
- (void)onStart:(UIButton*)sender
{
    NSLog(@"start %@",self.navigationItem.title);
    
    _workerqueue = dispatch_queue_create("myworkerqueue", DISPATCH_QUEUE_SERIAL);
    
    
}
static int iCnt = 0;
- (void)onAddTask:(UIButton*)sender
{
    iCnt++;
    
    ////////////
    {
        __block int iThis = iCnt;
        NSLog(@" onAddTask ...%d",iThis);
        dispatch_async(self.workerqueue, ^{
           //
            NSLog(@"add and eat the task  ...%d", iThis);
            sleep(2);
            NSLog(@"eat up task %d",iThis);
        });
    }
}

前面兩種常駐執行緒都可以通過更改執行標誌來使執行緒停止迴圈走到函式尾,結束這個執行緒,但是GCD的queue卻沒有這個。暫時不知道怎麼回收這個資源,估計使用與

dispatch_queue_create對應的 xxxx release之類的吧。沒有研究過。
好了,暫時實驗了這麼幾種常駐執行緒方式,這個需求場景其實很普遍:比方 介面的互動操作背後的一些列業務邏輯 都可以丟在常駐執行緒上去計算,避免頁面的卡頓,減輕主執行緒的計算操作。

這時候需要設計任務佇列模型,對於邏輯層的各種業務就有跡可循了,一個一個執行的嘛。不管你介面怎麼互動的,我的邏輯層都是一個一個執行,而且可以對任務做一些額外的統一處理:失敗自動重試,日至記錄等等

不過,目前我的App裡面暫時沒有采用任務佇列模式,都是觸發式的,介面觸發則一條道走到黑。其實這樣是不好的,介面觸發一個,你就的有一條道對應,道多不說,而且難以維護。我測試的程式碼 稍後上傳。

程式碼來啦,這裡