NSRunloop的解析及autorelease的釋放時機
http://blog.csdn.net/xinruiios/article/details/8929915
iOS的執行時是由一個一個runloop組成的,每個runloop都會執行下圖所示的一些步驟:
每個runloop中都建立一個Autorelease Pool,並在runloop的末尾進行釋放,
所以,一般情況下,每個接受autorelease訊息的物件,都會在下個runloop開始前被釋放。也就是說,在一段同步的程式碼中執行過程中,生成的物件接受autorelease訊息後,一般是不會在程式碼段執行完成前釋放的。
當然也有讓autorelease提前生效的辦法:自己建立Pool並進行釋放
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSArray * array = [[[NSArray alloc] init] autorelease];
[pool drain];
上面的array就會在[pool drain]執行時被釋放。
所以對於你遇到的問題,可以在for迴圈外巢狀一個Autorelease Pool進行管理,例如
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
for (int i = 0; i < 10000; i++)
{
// ...
}
[pool drain];
但由於你提到了生成的每個例項可能會比較大。只在迴圈外巢狀,可能導致在pool釋放前,記憶體裡已經有10000個例項存在,造成瞬間佔用記憶體過大的情況。
因此,如果你的每個例項僅需要在單次迴圈過程中用到,那麼可以考慮可以在迴圈內建立pool並釋放
for (int i = 0; i < 10000; i++)
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// ...
[pool drain];
}
執行緒中沒有source的runloop會自動結束。
事件由NSRunLoop 類處理。RunLoop監視作業系統的輸入源,如果沒有事件資料,不消耗任何CPU 資源。如果有事件資料,run loop 就傳送訊息,通知各個物件。
用 currentRunLoop 獲得 runloop的 reference,給 runloop 傳送run 訊息啟動它。
下面介紹四種情況是使用runloop的場合:
1.使用埠或自定義輸入源和其他執行緒通訊
2.子執行緒中使用了定時器
3.cocoa中使用任何performSelector到了執行緒中執行方法
4.使執行緒履行週期性任務,(我把這個理解與2相同)
如果我們在子執行緒中用了NSURLConnection非同步請求,那也需要用到runloop,不然執行緒退出了,相應的delegate方法就不能觸發。
這裡通過小示例簡單介紹以下有關runloop方面的問題:
1.首先簡單執行執行runlooprun函式並不會讓系統停住等待事件,而是需要在執行runloop之前新增source,只有在有source的情況下執行緒才會停下來監聽各種事件。
2.runloop的使用:
1)生成一個runloop source
// add send source
CFRunLoopSourceContext src_context ;
NSError * emsg = nil ;
// init send source context
src_context.version = 0;
src_context.info = inst;
src_context.retain = NULL;
src_context.release = NULL;
src_context.copyDescription = NULL;
src_context.equal = NULL;
src_context.hash = NULL;
src_context.schedule = NULL;
src_context.cancel = NULL;
src_context.perform = &callback ;//設定喚醒是呼叫的回撥函式
// create send source from context
CFRunLoopSourceRef runloopSource ;
runloopSource = CFRunLoopSourceCreate (NULL, 0, &src_context) ;
2)將source加入執行緒所屬的runloop中
// add the send source into run loop
CFRunLoopRef threadRunLoop ;
threadRunLoop = CFRunLoopGetCurrent() ;
CFRunLoopAddSource (threadRunLoop ,
runloopSource,
kCFRunLoopDefaultMode);
3)執行runloop
CFRunLoopRun() ;
4)如何呼叫runloop(首先可以將各個執行緒的runloop和source儲存起來)
CFRunLoopSourceSignal(runloopSource) ;// 引數是你呼叫的runloop的source
CFRunLoopWakeUp(threadRunLoop) ;//這句話的作用時立即執行該runloop的事件,如果沒有這句話系統會在空閒的時候執行剛才的runloopSource相關的事件
3.如何停掉runloop退出執行緒
CFRunLoopStop(threadRunLoop) ;這個函式可以停掉runloop是執行緒正常退出
4.ios整個系統基本上是基於runloop這種架構的,ios程式的main執行緒整體上也是基於runloop的,各種事件的響應應該也是基於source這種思路。
相關文章
- iOS開發 自動釋放池(Autorelease Pool)和RunLoopiOSOOP
- 《NSRunLoop》OOP
- IOS基礎:retain,copy,assign及autoreleaseiOSAI
- golang 釋放記憶體機制的探索Golang記憶體
- 開啟linux主機的埠快速釋放Linux
- 80埠被佔用及如何釋放80埠的方法
- 釋放並執行病毒及風險程式的木馬(轉)
- 程式退出時如何保證佔用的埠完全釋放?
- UIViewController及UIView未deinit釋放UIViewController
- Linux釋放記憶體及手動釋放Oracle共享記憶體段Linux記憶體Oracle
- iOS多執行緒的初步研究(三)-- NSRunLoopiOS執行緒OOP
- vector 的記憶體釋放記憶體
- 有時發現系統記憶體不釋放臨時採用辦法,寫成指令碼,定時去釋放記憶體指令碼
- iOS-autorelease與autoreleasepooliOS
- 也來談談CFRunLoop(NSRunLoop)OOP
- SQLServer如何釋放tempdb臨時表空間SQLServer
- 深入解析 TiFlash丨多併發下執行緒建立、釋放的阻塞問題執行緒
- TCP連結的建立和釋放TCP
- oracle 的臨時表解析及與其SQLSERVER的比較(轉載)OracleSQLServer
- 螞蟻金服通訊框架 SOFABolt 解析 | 超時控制機制及心跳機制框架
- (轉載)iOS 底層解析weak的實現原理(包含weak物件的初始化,引用,釋放的分析)iOS物件
- 釋放檔案到臨時資料夾中所引發的安全問題
- linux檢視埠占用及強制釋放埠Linux
- 各個執行緒 Autorelease 物件的記憶體管理執行緒物件記憶體
- 再談mysql鎖機制及原理—鎖的詮釋MySql
- Cocos2dx-記憶體管理機制(autorelease、release、retain)記憶體AI
- 正確釋放Vector的記憶體記憶體
- 程式怎樣釋放指向物件的引用物件
- 使用runtime Associate方法關聯的物件,需要在主物件dealloc的時候釋放麼?物件
- Linux: 如何檢視本機埠並釋放Linux
- Promise的實現及解析Promise
- 又是訊號量和共享記憶體沒有釋放的db待機記憶體
- 誰建立誰銷燬,誰分配誰釋放——JNI呼叫時的記憶體管理記憶體
- vuejs在解析時出現閃爍的原因及防止閃爍的方法VueJS
- iOS開發那些事-效能優化–autorelease的使用問題iOS優化
- 釋放ip埠
- DBMS_LOB的簡單用法以及釋放DBMS_LOB生成的臨時CLOB記憶體記憶體
- 【PB】事件的觸發時機及先後順序事件