上篇我們學(xué)習(xí)了iOS多線程解決方式中的NSOperation妹笆,這篇我主要概況總結(jié)iOS多線程中NSThread的解決方式和基本用例
一.iOS多線程對(duì)比
- NSThread
每個(gè)NSThread對(duì)象對(duì)應(yīng)一個(gè)線程汉嗽,真正最原始的線程
- 優(yōu)點(diǎn):
NSThread
輕量級(jí)最輕藐翎,相對(duì)簡(jiǎn)單 - 缺點(diǎn):手動(dòng)管理所有的線程活動(dòng),如生命周期寝优、線程同步、睡眠等
- NSOperation
自帶線程管理的抽象類
- 優(yōu)點(diǎn):自帶線程周期管理,操作上可更注重自己邏輯
- 缺點(diǎn):面向?qū)ο蟮某橄箢惼墙。荒軐?shí)現(xiàn)它或者使用它定義好的兩個(gè)子類:
NSInvocationOperation
和NSBlockOperation
- GCD
Grand Central Dispatch 是Apple開發(fā)的一個(gè)多核編程的解決方法。
- 優(yōu)點(diǎn):最高效插勤,避開并發(fā)陷阱
- 缺點(diǎn):基于C實(shí)現(xiàn)
- 選擇小結(jié)
- 簡(jiǎn)單而安全的選擇NSOperation實(shí)現(xiàn)多線程即可
- 處理大量并發(fā)數(shù)據(jù)沽瘦,又追求性能效率的選擇GCD
- NSThread較麻煩,不建議使用
二. 場(chǎng)景選擇
- 圖片異步加載:這種常見的場(chǎng)景是最常見也是必不可少的农尖,異步加載圖片又分成兩種
- 在UI主線程開啟新線程按順序加載圖片析恋,加載完成刷新UI
- 依然是在主線程開啟新線程,順序不定的加載圖片盛卡,加載完成后刷新UI
- 創(chuàng)作工具上的異步:這個(gè)跟上邊任務(wù)調(diào)度道理差不多助隧,只是為了豐富描述,有助于“舉一反三”效果滑沧,如下描述的是APP創(chuàng)作小說
- app本地創(chuàng)作10個(gè)章節(jié)內(nèi)容完成同步服務(wù)器并村,接著同時(shí)發(fā)表這10個(gè)章節(jié)將產(chǎn)生的一系列動(dòng)作,其中上傳內(nèi)容嚎货,獲取分配章節(jié)Id橘霎,如果后臺(tái)沒有做處理最好方式做異步按順序執(zhí)行。
- app本地創(chuàng)作列表中有3本小說要發(fā)表殖属,如果同時(shí)發(fā)表創(chuàng)作列表中的3本小說姐叁,自然考慮并行隊(duì)列執(zhí)行發(fā)表。
三.使用方法
- 三種實(shí)現(xiàn)開啟線程方式:
- 動(dòng)態(tài)實(shí)例化
NSThread * thread = [[NSThread alloc] initWithTarget:self selector:@selector(loadImageSource:) object:imgUrl];
thread.threadPriority = 1; //設(shè)置線程的優(yōu)先級(jí)(0.0 - 1.0, 1.0最高級(jí))
[thread start];
- 靜態(tài)實(shí)例化
[NSThread detachNewThreadSelector:@selector(loadImageSource:) toTarget:self withObject:imgUrl];
- 隱式實(shí)例化
[self performSelectorOnMainThread:@selector(loadImageSource:) withObject:self waitUntilDone:imgUrl];
代碼示例:
//
// ViewController.m
// TestNSThread
//
// Created by taobaichi on 2017/3/21.
// Copyright ? 2017年 MaChao. All rights reserved.
//
#import "ViewController.h"
#define imgUrl @"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg"
@interface ViewController ()
@property (nonatomic, strong) UIImageView * imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.imageView = [[UIImageView alloc]initWithFrame:CGRectMake(self.view.frame.size.width /2 - 100, self.view.frame.size.height / 2 - 100, 200, 200)];
self.imageView.backgroundColor = [UIColor purpleColor];
[self.view addSubview:self.imageView];
[self dynamicCreateThread];
}
//動(dòng)態(tài)創(chuàng)建線程
-(void)dynamicCreateThread{
NSThread * thread = [[NSThread alloc] initWithTarget:self selector:@selector(loadImageSource:) object:imgUrl];
thread.threadPriority = 1; //設(shè)置線程的優(yōu)先級(jí)(0.0 - 1.0 1.0最高級(jí))
[thread start];
}
//靜態(tài)創(chuàng)建線程
-(void)staticCreateThread{
[NSThread detachNewThreadSelector:@selector(loadImageSource:) toTarget:self withObject:imgUrl];
}
//隱式創(chuàng)建線程
-(void)implicitCreateThread{
[self performSelectorInBackground:@selector(loadImageSource:) withObject:imgUrl];
}
-(void)loadImageSource:(NSString *)url
{
NSData * imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
UIImage * image = [UIImage imageWithData:imgData];
if (imgData != nil) {
//回到主線程刷新UI
[self performSelectorOnMainThread:@selector(refreshImageView:) withObject:image waitUntilDone:YES];
}else{
NSLog(@"there no image data");
}
}
-(void)refreshImageView:(UIImage *)image{
[self.imageView setImage:image];
}
@end
2.NSThread的拓展認(rèn)識(shí)
- 獲取當(dāng)前線程
NSThread * current = [NSThread currentThread];
- 獲取主線程
NSThread * main = [NSThread mainThread];
- 暫停當(dāng)前線程
[NSThread sleepForTimeInterval:2.0];
- 線程之間通信
//在指定線程上執(zhí)行
[self performSelector:@selector(refreshImageView:) onThread:thread withObject:image waitUntilDone:YES];
//在主線程執(zhí)行
[self performSelectorOnMainThread:@selector(refreshImageView:) withObject:image waitUntilDone:YES];
//在后臺(tái)執(zhí)行
[self performSelectorInBackground:@selector(refreshImageView:) withObject:image];
//在當(dāng)前 線程上執(zhí)行
[self performSelector:@selector(refreshImageView:) withObject:image];