線程的可選方案objective-c
有時候,你不想繼承threads或不想本身建立和管理單獨的線程。例如,你想要一個定時器每2秒鐘調用你的方法,你可能會寫一個線程一直循環,而後睡眠2秒,而後調用你的方法。或者你可能想要寫代碼處理異步請求,好比從網絡上下載文件。或者當你的iPhone空閒時,你想要繼續進行重量級的計算處理。這些都不太容易實現或者可能會下降性能。我會討論一些解決的辦法。安全
NSTimer服務器
NSTimer並不承諾會很精確;若是你設置每0.5秒觸發一次,實際上定時器觸發的時間可能在0.55和0.6秒之間。可是,若是你只是想相對準確的執行週期性任務的話,這是一個很好的機制。網絡
重複和非重複NSTimer比較多線程
你能夠執行重複或非重複的定時器。對於重複的定時器來講,定時器會在你指定的時間間隔內觸發,不會中止。若是你想中止的話,你須要手工的使定時器無效。對於非重複定時器來講,它只會觸發一次,而後會自動的變爲無效。對這兩種狀況,一旦定時器無效了,你不能在重用它;你必須從新建立一個定時器對象。異步
要建立一個定時器,你可使用:ide
+ scheduledTimerWithTimeInterval:target:selector:userInfo: repeats: 函數
或使用:oop
+ timerWithTimeInterval:target:selector:userInfo:repeats: post
第一種方法會建立一個新的定時器,而後添加到當前的run loop中,而後返回定時器對象給你。第二種方法僅僅建立一個定時器對象;你須要本身經過調用[aTimer addTimer: forMethod]來添加到你本身的run loop中。
當時候重複定時器時,若是你要使定時器變成無效的話,你須要調用方法:[aTimer invalidate];
注意:在一個沒有run loop的線程中,NSTimer是不能工做的。 |
異步函數
在不少狀況下,異步函數比線程更輕量級。例如,iPhone環境可以從線程池中重用線程來處理異步函數。更進一步,若是你須要處理100個異步函數,OS可能只須要10個線程,由於一個線程可以處理多個異步函數。惟一的問題就是,它比你建立一些線程和一個異步請求來處理他們看起來更復雜。
Listing 6-9 代碼塊建立了一個異步請求到服務器上,而後合併返回的結果建立一個數據對象。
相比,使用簡單的線程和異步函數處理方案:
@autoreleasepool {
NSData *p_w_picpathData = [NSData dataWithContentsOfURL:p_w_picpathURL];
}
在某些狀況下,你可能須要寫更多的代碼來得到更好的性能。你僅僅須要確保實際上作的什麼將對你有利。
若是你使用異步HTTP請求,你須要運行在一個後臺線程中。若是很長一段時間都沒有響應,iOS的策略可能會殺掉你的應用。這會使得你的應用給別人一個很差的印象。
注意:若是你同時有不少HTTP調用,你應該考慮建立一個單獨的線程來處理異步調用,從而避免在主線程上調用衝突。 |
Idle-Time Notifications 空閒通知
有些事情你只想在系統空閒的時候作。例如,你想要從iPhone發送反饋到服務器上,而你又不想在其餘處理正在進行或其餘用戶正在和設備交互的時候發送。你只想在用戶或設備沒事可作的時候發送。若是是你本身的話,這確實是一個很難的事情。不太高興的是,蘋果已經提供了一個函數來處理了。你能夠經過NSNotificationQueue 使用 NSPostWhenIdle類型 來post一個通知,像下面的代碼:
你能夠看到,它就像使用NSNotificationCenter那樣來使用;你添加一個對象和方法做爲觀察者和selector。而後你能夠post一個新的通知到隊列中,這樣方法就會在系統空閒的時候進行處理。
iPhone線程測試
線程的測試在第二章已經討論過了,因此圖6-13只是一個簡單的溫習。
這個測試並無提供太多的信息,除了應用中當前線程的狀態。這個可以幫助你瞭解系統是否由於使用太多線程致使負荷太重,或線程掛起和等待太長時間,這是死鎖的一個徵兆。
總結
在本章,你學到了如何使用多線程來提高你應用的性能。概念其實是很是簡單的:你建立一個新的線程來處理一些計算。可是,爲了使得你的應用正確和安全的運行,你須要注意不少細節。你一樣須要知道cpu密集型任務和IO密集型任務,來確保什麼會致使性能提高,或使得性能降低。你學到了如何用不一樣的方法建立,管理,運行線程。你一樣學到了使用鎖的objective-c風格和它的語法,線程同步的問題,這個其實是很是重要的。