RunLoop之執行緒保活

2021-10-08 18:34:43 字數 3680 閱讀 8146

參考文獻

在ios專案中,有時會有一些花費時間較長的操作阻塞主線程,我們通常為了防止介面卡頓,將其放入子執行緒中執行。根據執行緒知識,如果子執行緒執行完分配的任務後,就會自動銷毀。

比如我們現在定義乙個執行緒,改寫它的dealloc方法,觀察它什麼時候銷毀

@implementation taythread-(

void

)dealloc

@end

在viewcontroller裡新建乙個taythread子執行緒,讓它去執行任務

@implementation viewcontroller-(

void

)viewdidload -(

void

)dosomething

@end

根據列印結果我們可以看到,在子執行緒執行完任務後執行緒自動銷毀。

而我們有時會需要經常在乙個子執行緒中執行任務,頻繁的建立和銷毀執行緒就會造成資源浪費,這時候就要用到runloop來使執行緒長時間存活了,我們稱之為執行緒保活

我們首先需要建立乙個runloop。

注意:runloop直接獲取就可以,沒有的話會在第一次獲取時建立;如果runloop 中的 modes 為空,或者要執行的mode裡沒有item,那麼runloop會直接在當前runloop中返回,並進入睡眠狀態。即dosomething改為:

根據列印結果可以知道,方法並沒有執行完畢。我們希望的是在子執行緒執行完任務後就睡覺等待被喚醒,這樣子寫相當於雖然該任務執行完了但是runloop一直卡在這裡,也不能去執行別的任務。顯而易見,這種辦法是不夠完美的。

官方文件中提到有三種啟動runloop的方法:

方法名介紹

中文翻譯

rununconditionally

無條件rununtildate

with a set time limit

設定時間限制

runmode:beforedate:

in a particular mode

在特定模式下

對於三種方法介紹總結如下:

檢視 run 方法的文件還可以知道,它的本質就是無限呼叫 runmode:beforedate: 方法,同樣地,rununtildate: 也會重複呼叫 runmode:beforedate:,區別在於它超時後就不會再呼叫

也就是說,只有runmode:beforedate:方法是單次呼叫,其他兩種都是迴圈呼叫

在處理事件之前,有兩種方法可以使執行迴圈退出:

如果你使用方法二或三來啟動 runloop,那麼在啟動的時候就可以設定超時時間。然而考慮到我們的目標是:「利用 runloop 進行執行緒保活」,所以我們希望對執行緒和它的 runloop 有最精確的控制,比如在完成任務後立刻結束,而不是依賴於超時機制

根據文件描述,我們有乙個 cfrunloopstop() 方法來手動結束乙個 runloop

注意:cfrunloopstop() 方法只會結束當前的 runmode:beforedate: 呼叫,而不會結束後續的呼叫

通過以上關於runloop啟動和關閉的方法分析,我們大概有這樣乙個思路:

我們想要控制runloop,就需要使用runmode:beforedate:方法,因為其他兩種方法乙個無法停止乙個只能依賴超時機制

cfrunloopstop() 方法只會結束當前的一次的runmode:beforedate:方法呼叫,我們必須再做點什麼

針對以上疑問,有以下解答:

首先,因為runmode:beforedate:方法是單次呼叫,我們需要給它加上乙個迴圈,否則呼叫一次就over了,和不使用runloop的效果大同小異

這個迴圈的條件可以預設設定為yes,當呼叫stop方法時,執行cfrunloopstop() 方法並且將迴圈條件改為no,就可以使迴圈停止,runloop退出

**長這樣:

@inte***ce viewcontroller (

)@property

(strong, nonatomic) taythread *athread;

@property

(assign, nonatomic, getter=isstoped) bool stopped;

@end

@implementation viewcontroller-(

void

)viewdidload

nslog

(@"ok");

}];[

self

.athread start];}

-(void

)touchesbegan:

(nsset

>

*)touches withevent:

(uievent *

)event

// 子執行緒需要執行的任務-(

void

)dosomething -(

void

)stop

// 用於停止子執行緒的runloop-(

void

)stopthread -(

void

)dealloc

後來又發現還存在一些問題,如果將上述**寫入乙個newviewcontroller,當該viewcontroller已經dealloc時,執行緒並沒有死,這就造成了記憶體洩漏了。我這個執行緒是為了這個viewcontroller而活的,viewcontroller都死掉了,執行緒怎麼能還活著呢,下面是修改後的

#import "newviewcontroller.h"

#import "taythread.h"

@inte***ce newviewcontroller (

)@property

(strong, nonatomic) taythread *athread;

@property

(assign, nonatomic, getter=isstoped) bool stopped;

@end

@implementation newviewcontroller-(

void

)viewdidload

nslog

(@"ok");

}];[

self

.athread start];}

-(void

)touchesbegan:

(nsset

>

*)touches withevent:

(uievent *

)event

// 子執行緒需要執行的任務-(

void

)dosomething -(

void

)stop

}// 用於停止子執行緒的runloop-(

void

)stopthread -(

void

)dealloc -(

void

)back

深入研究 runloop 與執行緒保活

ios開發-使用runloop實現執行緒保活、執行緒常駐

如何實現執行緒保活

有兩種方案 第一種 提公升優先順序 降低程序被殺死的概率 執行緒的優先順序 a.前台程序 b.可見程序 c.服務程序 d.後台程序 e.空程序 1.利用activity 提公升許可權 監聽手機鎖屏事件 在螢幕鎖屏的時候啟動乙個 1畫素的 activity,在使用者解鎖時將 activity 銷毀,注...

ios 執行緒休眠 iOS執行緒保活(常駐執行緒)

介紹 在日常的ios開發中,遇到卡頓也是在所難免,一般卡頓是由於主線程處理耗時長的操作而造成執行緒一直在阻塞,那麼我們可以去建立子執行緒,把耗時操作放在子執行緒去做,這樣是完全沒問題。這樣就會有乙個問題,子執行緒處理完操作之後就會被銷毀,想再處理其他事情,必須再開啟新的子執行緒。如果想要乙個子執行緒...

跑步app保活 android APP保活機制

摘要 1,從官網上可以看出google為了系統更加流暢以及優化記憶體,google做了很大的處理,在手機暗屏或者睡眠狀態就停止後台執行 若要保持service的常駐,需要做一些前端的活動,notification重要屬性 notification.flags notification.flag no...