進(jìn)程:內(nèi)存里的一個(gè)程序就是一個(gè)進(jìn)程,運(yùn)行起來的程序就是一個(gè)進(jìn)程,程序并不能單獨(dú)運(yùn)行,只有將程序裝載到內(nèi)存中,系統(tǒng)為它分配資源才能運(yùn)行,每個(gè)進(jìn)程均運(yùn)行在其專用且受保護(hù)的內(nèi)存空間內(nèi),而這種執(zhí)行的程序就稱之為進(jìn)程。程序和進(jìn)程的區(qū)別就在于:程序是指令的集合,它是進(jìn)程運(yùn)行的靜態(tài)描述文本;進(jìn)程是程序的一次執(zhí)行活動(dòng),屬于動(dòng)態(tài)概念。
線程:線程是指進(jìn)程內(nèi)的一個(gè)執(zhí)行單元,也是進(jìn)程內(nèi)的可調(diào)度實(shí)體,一個(gè)應(yīng)用至少有一個(gè)線程(主線程)(IOS中UI主線程)
iOS有三種多線程編程的技術(shù),分別是: (一)NSThread (二)Cocoa NSOperation (三)GCD(全稱:Grand Central Dispatch)
這三種編程方式從上到下,抽象度層次是從低到高的,抽象度越高的使用越簡(jiǎn)單,也是Apple最推薦使用的。
NSThread
- 優(yōu)點(diǎn):NSThread 比其他兩個(gè)輕量級(jí)
- 缺點(diǎn):需要自己管理線程的生命周期,線程同步。線程同步對(duì)數(shù)據(jù)的加鎖會(huì)有一定的系統(tǒng)開銷
-(void)downloadImage:(NSString *) url{
NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
UIImage *image = [[UIImage alloc] initWithData:data];
if(image == nil){
} else{
[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
}
}
-(void)updateUI:(UIImage*) image{
self.imageView.image = image;
}
- (void)viewDidLoad {
[super viewDidLoad];
// [NSThread detachNewThreadSelector:@selector(downloadImage:) toTarget:self withObject:kURL];
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(downloadImage:) object:kURL];
[thread start];
}
NSOperation
使用 NSOperation的方式有兩種,一種是用定義好的兩個(gè)子類:NSInvocationOperation 和 NSBlockOperation。另一種是繼承NSOperation。
- (void)viewDidLoad{
[super viewDidLoad];
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage:) object:kURL];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];
}
-(void)downloadImage:(NSString *)url{
NSURL *nsUrl = [NSURL URLWithString:url];
NSData *data = [[NSData alloc] initWithContentsOfURL:nsUrl];
UIImage * image = [[UIImage alloc] initWithData:data];
[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
}
-(void)updateUI:(UIImage*) image{
self.imageView.image = image;
}
GCD
dispatch_queue_t queue =dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
//1.獲取網(wǎng)址字符串
NSString * urlString = @"http://www./uploads/allimg/121230/1-121230094954.jpg";
//2.NSString->NSURL
NSURL * url = [NSURL URLWithString:urlString];
//3.同步下載
NSData * data = [NSData dataWithContentsOfURL:url];
UIImage * image = [UIImage imageWithData:data];
dispatch_sync(dispatch_get_main_queue(), ^{
self.view.backgroundColor = [UIColor colorWithPatternImage:image];
});
});
P.S. 子線程里面不能更行主線程的UI 只有主線程能夠更新UI,其他都不行
-
子線程沒有能力去更新主線程的UI,我們之所以能夠看到某些時(shí)候更新了的效果,是因?yàn)樽泳€程結(jié)束,立刻回到了主線程中,主線程更新子線程里面要求的UI,由于子線程結(jié)束回到主線程的時(shí)間比較短,因此造成了一種誤解,以為是子線程更新了UI,實(shí)則是UI主線程自己做的
-
如果在子線程里面直接更新UI, 可能會(huì)造成兩種錯(cuò)誤 a. UI的更新不及時(shí),必須等子線程結(jié)束了,主線程才會(huì)去更新UI b. 當(dāng)子線程還沒有結(jié)束,主線程中已經(jīng)將UI元素釋放,那么當(dāng)子線程結(jié)束了,回到主線程中,就會(huì)去繼續(xù)更新這個(gè)UI元素,可是UI已經(jīng)沒有了,造成內(nèi)存錯(cuò)誤
-
當(dāng)子線程執(zhí)行完畢,立刻返回到主線程,如果子線程有需要讓主線程做一定的事情,那么主線程會(huì)掛起其他的任務(wù),執(zhí)行這些事情
參考資料 關(guān)于iOS多線程,你看我就夠了 iOS開發(fā)多線程篇—GCD介紹 iOS多線程編程之Grand Central Dispatch(GCD)介紹和使用
|