標籤:tar get 使用 檔案 資料 art
多線程
1.多線程的原理
1>.同一時間,CPU只能處理1條線程,只有1條線程在工作(執行)
2>.多線程並發(同時)執行,其實是CPU快速地在多條線程之間調度(切換)
3>.如果CPU調度線程的時間足夠快,就造成了多線程並發執行的假象
如果線程非常非常多,會發生:
1>.CPU會在N多線程之間調度,CPU會累死,消耗大量的CPU資源
2>.每條線程被調度執行的頻次會降低(線程的執行效率降低)
2.多線程的優缺點
1>.多線程的優點
能適當提高程式的執行效率
能適當提高資源使用率(CPU、記憶體利用率)
2>.多線程的缺點
開啟線程需要佔用一定的記憶體空間(預設情況下,主線程佔用1M,子線程佔用512KB),如果開啟大量的線程,會佔用大量的記憶體空間,降低程式的效能
線程越多,CPU在調度線程上的開銷就越大
程式設計更加複雜:比如線程之間的通訊、多線程的資料共用
3.主線程
一個iOS程式運行後,預設會開啟1條線程,稱為“主線程”或“UI線程”
1>.主線程的主要作用
顯示\重新整理UI介面
處理UI事件(比如點擊事件、滾動事件、拖拽事件等)
2>.主線程的使用注意
別將比較耗時的操作放到主線程中
耗時操作會卡住主線程,嚴重影響UI的流暢度,給使用者一種“卡”的壞體驗
4.NSThread
1> 開線程的幾種方式
* 先建立,後啟動
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[thread start];
* 直接啟動
a>.[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
b>.[self performSelectorInBackground:@selector(run) withObject:nil];
2> 其他用法
NSThread *current = [NSThread currentThread]; // 擷取當前線程
+ (NSThread *)mainThread; // 獲得主線程
+ (void)exit; // 強制停止線程
* 阻塞(暫停)線程
+ (void)sleepUntilDate:(NSDate *)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
3> 同步鎖(互斥鎖)
1塊資源可能會被多個線程共用,也就是多個線程可能會訪問同一塊資源,比如多個線程訪問同一個對象、同一個變數、同一個檔案,當多個線程訪問同一塊資源時,很容易引發資料錯亂和資料安全問題
同步鎖的使用前提:多條線程搶奪同一塊資源
a>.同步鎖使用格式
@synchronized(鎖對象) { // 需要鎖定的代碼 }
注意:鎖定1份代碼只用1把鎖,用多把鎖是無效的
b>.同步鎖的優缺點
優點:能有效防止因多線程搶奪資源造成的資料安全問題
缺點:需要消耗大量的CPU資源
c>.線程同步
線程同步的意思是:多條線程按順序地執行任務
同步鎖,就是使用了線程同步技術
4> 線程間通訊
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;
2.GCD(重點)
1> GCD的優勢
GCD是蘋果公司為多核的並行運算提出的解決方案
GCD會自動利用更多的CPU核心(比如雙核、四核)
GCD會自動管理線程的生命週期(建立線程、調度任務、銷毀線程)
程式員只需要告訴GCD想要執行什麼任務,不需要編寫任何線程管理代碼
2> 隊列的類型
* 並發隊列
獲得全域的並發隊列: dispatch_get_global_queue
* 串列隊列
a.自己建立: dispatch_queue_create
b.主隊列: dispatch_get_main_queue
並發和串列決定了任務的執行方式
並發:多個任務並發(同時)執行
串列:一個任務執行完畢後,再執行下一個任務
3> 執行任務的方法類型
* 同步(sync)執行
* 非同步(async)執行
同步和非同步決定了要不要開啟新的線程
同步:在當前線程中執行任務,不具備開啟新線程的能力
非同步:在新的線程中執行任務,具備開啟新線程的能力
4> 線程間通訊
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 執行耗時的非同步作業...
dispatch_async(dispatch_get_main_queue(), ^{
// 回到主線程,執行UI重新整理操作
});
});
5> 其他用法
dispatch_once // 用於單例對象
dispatch_after // 消極式載入
dispatch_group_async\dispatch_group_notify // 隊列組
3.NSOperation
1> 基本使用
a>.NSInvocationOperation : - (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;
b>.NSBlockOperation : + (id)blockOperationWithBlock:(void (^)(void))block;
- (void)addExecutionBlock:(void (^)(void))block; // 添加操作
只要NSBlockOperation封裝的運算元 > 1,就會非同步執行操作
2> NSOperationQueue(重點)
*添加操作到NSOperationQueue中
- (void)addOperation:(NSOperation *)op;
- (void)addOperationWithBlock:(void (^)(void))block;
* 最大並發數設定
- (NSInteger)maxConcurrentOperationCount;
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;
*取消隊列的所有操作
- (void)cancelAllOperations;
提示:也可以調用NSOperation的- (void)cancel方法取消單個操作
*暫停和恢複隊列
- (void)setSuspended:(BOOL)b; // YES代表暫停隊列,NO代表恢複隊列
- (BOOL)isSuspended;
* 設定依賴(面試題)
[operationB addDependency:operationA]; // 操作B依賴於操作A
3> 自訂Operation(瞭解基本流程)
重寫- (void)main方法,在裡面實現想執行的任務
重寫- (void)main方法的注意點
自己建立自動釋放池(因為如果是非同步作業,無法訪問主線程的自動釋放池)
經常通過- (BOOL)isCancelled方法檢測操作是否被取消,對取消做出響應
4> 如何解決一張圖片(一個url)重複下載的問題(面試題)
使用字典或對象根據url儲存下載的非同步作業,判斷這個非同步作業是否存在,存在就不在建立