一、基本概念編程
什麼是進程: 進程是在系統運行的一個程序,每一個進程之間是獨立的,每一個進程均運行在其專有且受保護的內存空間內。網絡
什麼是線程: 一個進程想要執行任務,必須得有線程(至少一個線程),線程是進程的基本執行單位,一個進程的全部任務都必須在線程中執行。多線程
線程的串行: 一個線程中任務的執行是串行的,若是要在一個線程中執行多個任務,只能一個一個的按順序執行併發
二、多線程框架
什麼是多線程:性能
一個進程中能夠開啓多個線程,每一個線程能夠併發/並行執行不一樣的任務,多線程能夠提交程序的執行效率,好比同時執行任務ABC。線程
多線程原理:調試
同一時間,CPU只能執行一個線程,只有一個線程正在執行,多線程併發執行,實際上是CPU快速的在多個線程之間切換,若是CPU的切換線程的時間足夠快,就會形成多線程併發執行的假象。code
多線程的優缺點:orm
優勢: 1.能適當的提升程序的執行效率 2.能適當的提升資源的利用率 缺點: 1.開啓線程會佔用必定的內存空間(主線程1M,子線程0.5M),若是開啓過多的線程就會佔用大量的內存空間,下降程序的性能。 2.線程越多,CPU在調度線程上的開銷就越大。
三、主線程
一個IOS程序運行之後,默認會開啓一個線程,這個線程就被稱爲主線程或(UI線程)。主線程的主要做用是顯示/刷新UI界面,處理UI事件(點擊,滾動,拖拽等)。
IOS中的多線程:
iOS中有四種多線程編程的技術:
1.Pthread (基本不會使用,線程的生命週期由咱們⾃己管理)
2.NSThread(每一個Thread對象對應⼀一個線程)(使⽤用得⽐比較少,線程的⽣生命週期由咱們⾃己管理)
3.NSOperation(面向對象的線程技術)(基於gcd來實現,常常使⽤,⽣命週期由系統管理)
4.GCD(是基於C語⾔言的框架,能夠充分利用多核,是蘋果推薦使⽤的多線程技術)(常常使用,生命週期由系統管理))
以上這四種編程⽅方式從上到下,抽象度層次是從低到高的,抽象度越高的使用越簡單,也是Apple最推薦使用的。可是就目前而言,iOS的開發者,須要瞭解三種多線程技術的基本使⽤用過程。由於不少 框架技術分別使用了不一樣多線程技術。 代碼示例,用多線程加載圖片: 1、NSThread
#pragma 建立多個線程 -(void)loadImageViewWithThread{ //建立多個線程 9個圖片 for (int i=0; i<9; i++) { NSThread *thread=[[NSThread alloc]initWithTarget:self selector:@selector(myThread2:) object:[NSNumber numberWithInt:i]]; //線程的優先級只是提升優先被加載的概率,可是它未必是第一個加載 //網絡情況的制約 if(i==8){ thread.threadPriority=1; }else{ thread.threadPriority=0; } //能夠給線程一個名稱,方便調試、調用 thread.name=[NSString stringWithFormat:@"線程:%d",i]; //開始執行 [thread start]; } } #pragma 子線程,帶參數 -(void)myThread2:(NSNumber*)index{ //當不是最後一個線程時 if(![index isEqual:@8]){ //線程休眠2秒 [NSThread sleepForTimeInterval:2]; } //打印當前線程的名稱 NSLog(@"當前線程:%@",[NSThread currentThread].name); NSData*data=[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://a.hiphotos.baidu.com/zhidao/pic/item/e7cd7b899e510fb3bf607192da33c895d1430cbd.jpg"]]]; NSArray*array=@[data ,index]; [self performSelectorOnMainThread:@selector(upData:) withObject:array waitUntilDone:YES]; } #pragma 迴歸主線程 -(void)upData:(NSArray*)sender{ int index=[sender[1] intValue]; UIImageView *imageView=_imageViews[index]; imageView.image=[UIImage imageWithData:sender[0]]; }
2、NSOperation
#pragma NSOperation 開啓多線程 -(void)loadImageViewWithOperation{ //1.建立一個操做隊列(沒有順序) NSOperationQueue *opereatioQueue=[[NSOperationQueue alloc]init]; //設置最大併發線程數 opereatioQueue.maxConcurrentOperationCount=2; // //2.向隊列添加操做 // for (int i=0; i<15; i++) { // //方法1.建立操做快,添加到對列 //// NSBlockOperation*blockOperatio=[NSBlockOperation blockOperationWithBlock:^{ //// [self loadImageWith:i]; //// }]; //// [opereatioQueue addOperation:blockOperatio]; // //方法2.禱文invocation // NSInvocationOperation*invocationOperatio=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(loadImages:) object:[NSNumber numberWithInt:i]]; // [opereatioQueue addOperation:invocationOperatio]; //} //方法3.控制線程的執行順序,創建依賴操做關係 NSMutableArray *arr=[NSMutableArray array]; for (int i=0; i<_imageViews.count; i++) { //建立全部操做 NSBlockOperation*op1=[NSBlockOperation blockOperationWithBlock:^{ [self loadImages:[NSNumber numberWithInt:i]]; }]; [arr addObject:op1]; } for (int i=0; i<arr.count-1; i++) { //對操做進行依賴設置(後一個依賴前一個) [arr[i+1] addDependency:arr[i]]; } for (int i=0; i<arr.count; i++) { //把操做加入到隊列中 [opereatioQueue addOperation:arr[i]]; } } #pragma 代碼塊回調方法 -(void)loadImage:(int)index{ if(index==7){ NSData*data=[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://img.kejik.com/20151017/1445089621639.jpg"]]]; UIImageView*imageView=_imageViews[index]; imageView.image=[UIImage imageWithData:data]; }else{ NSData*data=[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://img.taopic.com/uploads/allimg/120505/154405-1205051U41588.jpg"]]]; UIImageView*imageView=_imageViews[index]; imageView.image=[UIImage imageWithData:data]; } } -(void)loadImageWith:(int )index{ NSData*data; if(index==7){ data=[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://img2.niutuku.com/desk/1207/1101/bizhi-1101-55018.jpg"]]]; }else{ data=[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://img.taopic.com/uploads/allimg/120505/154405-1205051U41588.jpg"]]]; } //迴歸主線程,更新UI [[NSOperationQueue mainQueue]addOperationWithBlock:^{ //主線程 UIImageView *imageView=_imageViews[index]; imageView.image=[UIImage imageWithData:data]; }]; } #pragma 禱文,子線程方法 -(void)loadImages:(NSNumber*)sender{ int index=[sender intValue]; NSData*data; if(index==7){ data=[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://www.ld12.com/upimg358/20160130/00230293571003.jpg"]]]; }else{ data=[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://img.taopic.com/uploads/allimg/120505/154405-1205051U41588.jpg"]]]; } //迴歸主線程,更新UI [[NSOperationQueue mainQueue]addOperationWithBlock:^{ //主線程 UIImageView *imageView=_imageViews[index]; imageView.image=[UIImage imageWithData:data]; }]; NSLog(@"%@",sender); }