iOS的運行時是由一個一個runloop組成的,每一個runloop都會執行下圖所示的一些步驟:ios
每一個runloop中都建立一個Autorelease Pool,並在runloop的末尾進行釋放,
因此,通常狀況下,每一個接受autorelease消息的對象,都會在下個runloop開始前被釋放。也就是說,在一段同步的代碼中執行過程當中,生成的對象接受autorelease消息後,通常是不會在代碼段執行完成前釋放的。多線程
固然也有讓autorelease提早生效的辦法:本身建立Pool並進行釋放架構
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];app
NSArray * array = [[[NSArray alloc] init] autorelease];異步
[pool drain];函數
上面的array就會在[pool drain]執行時被釋放。oop
因此對於你遇到的問題,能夠在for循環外嵌套一個Autorelease Pool進行管理,例如spa
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];
}
對於多線程來講,每個線程都有本身的runloop, 主線程是默認開啓的,建立的子線程要手動開啓,由於NSApplication只啓動main applicaiton thread。
線程中沒有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這種思路。