多線程整理

一: GCD(Grand Central Dispatch)->中樞調(diào)度器
1>. 存在的庫:
GCD存在于libdispatch.dylib這個庫中但狭,這個調(diào)度庫包含了GCD的所有的東西史汗,但任何IOS程序伴榔,默認(rèn)就加載了這個庫,在程序運行的過程中會動態(tài)的加載這個庫色迂,不需要我們手動導(dǎo)入。

. GCD是純C語言的,因此我們在編寫GCD相關(guān)代碼的時候幢炸,面對的函數(shù),而不是方法拒贱。
. GCD中的函數(shù)大多數(shù)都以dispatch開頭宛徊。
2>. 任務(wù)和隊列:
GCD中有2個核心概念
(1)任務(wù):執(zhí)行什么操作
(2)隊列:用來存放任務(wù)

GCD的使用就2個步驟
(1)定制任務(wù)
(2)確定想做的事情
3>. 執(zhí)行任務(wù):
.GCD中有2個用來執(zhí)行任務(wù)的函數(shù)
說明:把右邊的參數(shù)(任務(wù))提交給左邊的參數(shù)(隊列)進(jìn)行執(zhí)行。
(1)用同步的方式執(zhí)行任務(wù) dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
參數(shù)說明:
queue:隊列
block:任務(wù)
(2)用異步的方式執(zhí)行任務(wù) dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

4>. 同步和異步的區(qū)別
同步:在當(dāng)前線程中執(zhí)行
異步:在另一條線程中執(zhí)行

5>. 隊列的類型:
(1)并發(fā)隊列(Concurrent Dispatch Queue)
可以讓多個任務(wù)并發(fā)(同時)執(zhí)行(自動開啟多個線程同時執(zhí)行任務(wù))并發(fā)功能只有在異步(dispatch_async)函數(shù)下才有效
(2)串行隊列(Serial Dispatch Queue)
讓任務(wù)一個接著一個地執(zhí)行(一個任務(wù)執(zhí)行完畢后逻澳,再執(zhí)行下一個任務(wù))
GCD中獲得串行有2種途徑

6>. 創(chuàng)建隊列:
o1>. 串行隊列:
(1)使用dispatch_queue_create函數(shù)創(chuàng)建串行隊列

        dispatch_queue_t  dispatch_queue_create(const char *label,  dispatch_queue_attr_t attr); // 隊列名稱闸天, 隊列屬性,一般用NULL即可

示例:

        dispatch_queue_t queue = dispatch_queue_create("wendingding", NULL); // 創(chuàng)建
        dispatch_release(queue); // 非ARC需要釋放手動創(chuàng)建的隊列

(2)使用主隊列(跟主線程相關(guān)聯(lián)的隊列)
主隊列是GCD自帶的一種特殊的串行隊列,放在主隊列中的任務(wù)斜做,都會放到主線程中執(zhí)行
使用dispatch_get_main_queue()獲得主隊列

示例:

       dispatch_queue_t queue = dispatch_get_main_queue();

o2>. 并行隊列:
GCD默認(rèn)已經(jīng)提供了全局的并發(fā)隊列苞氮,供整個應(yīng)用使用,不需要手動創(chuàng)建
使用dispatch_get_global_queue函數(shù)獲得全局的并發(fā)隊列

dispatch_queue_t dispatch_get_global_queue(dispatch_queue_priority_t priority,unsigned long flags); // 此參數(shù)暫時無用瓤逼,用0即可

示例:
這個參數(shù)是留給以后用的笼吟,暫時用不上,傳個0霸旗。
第一個參數(shù)為優(yōu)先級贷帮,這里選擇默認(rèn)的。獲取一個全局的默認(rèn)優(yōu)先級的并發(fā)隊列诱告。

       dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 獲得全局并發(fā)隊列

<說明>. 全局并發(fā)隊列的優(yōu)先級:

#define DISPATCH_QUEUE_PRIORITY_HIGH 2 // 高
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默認(rèn)(中)
#define DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后臺

7>. 各種隊列的執(zhí)行效果:


242038164084931.png

<說明>. 同步函數(shù)與異步函數(shù):
(1). 用GCD同步執(zhí)行非UI相關(guān)的任務(wù)
目的:想要執(zhí)行那些不包含任何UI相關(guān)代碼的同步任務(wù)
方案:使用dispatch_sync 函數(shù)撵枢。
(2). 在GCD上異步執(zhí)行非UI相關(guān)任務(wù)
目的:你想要在GCD的幫助下能夠異步執(zhí)行非UI相關(guān)任務(wù)。
方案:主隊列蔬啡、串行隊列和并發(fā)隊列上異步執(zhí)行代碼塊才能見識到GCD的真正實力诲侮。(本書作者說,GCD會是多線程應(yīng)用的未來箱蟆,并將完全取代現(xiàn)代應(yīng)用中的線程)沟绪,千萬注意:不要再主隊列中使用同步執(zhí)行函數(shù)dispatch_sync
要在分派隊列上執(zhí)行異步任務(wù),你必須使用下面的這些函數(shù)中的其中一個:
dispatch_async 函數(shù)(在分派隊列上執(zhí)行一個 Block Object.)或者
dispatch_async_f函數(shù)(在分派隊列上執(zhí)行一個C函數(shù))

8>. 小結(jié)
同步函數(shù)不具備開啟線程的能力空猜,無論是什么隊列都不會開啟線程绽慈;異步函數(shù)具備開啟線程的能力恨旱,開啟幾條線程由隊列決定(串行隊列只會開啟一條新的線程,并發(fā)隊列會開啟多條線程)坝疼。

同步函數(shù)
(1)并發(fā)隊列:不會開線程
(2)串行隊列:不會開線程

異步函數(shù)
(1)并發(fā)隊列:能開啟N條線程
(2)串行隊列:開啟1條線程

補充:
凡是函數(shù)中搜贤,各種函數(shù)名中帶有create\copy\new\retain等字眼,都需要在不需要使用這個數(shù)據(jù)的時候進(jìn)行release钝凶。
GCD的數(shù)據(jù)類型在ARC的環(huán)境下不需要再做release仪芒。
CF(core Foundation)的數(shù)據(jù)類型在ARC環(huán)境下還是需要做release。
異步函數(shù)具備開線程的能力耕陷,但不一定會開線程

二: NSThread的使用:
<特點>:
優(yōu)點:NSThread 比其他兩個輕量級
缺點:需要自己管理線程的生命周期掂名,線程同步。線程同步對數(shù)據(jù)的加鎖會有一定 的系統(tǒng)開銷
1>. 創(chuàng)建:

- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument
+ (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument

第一個是實例方法哟沫,第二個是類方法

<selector方法實現(xiàn)>:

1饺蔑、[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];  
2、NSThread* myThread = [[NSThread alloc] initWithTarget:self  
                                        selector:@selector(doSomething:)  
                                        object:nil];  
     [myThread start];  

例子>.下載圖片的例子:

-(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];  
}

2>. 線程間通訊:
線程下載完圖片后怎么通知主線程更新界面呢嗜诀?
[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
performSelectorOnMainThread是NSObject的方法猾警,除了可以更新主線程的數(shù)據(jù)外,還可以更新其他線程的比如:用:performSelector:onThread:withObject:waitUntilDone:

三:NSOperation和NSOperationQueue的使用:
1>. 使用NSOperation的方式:
(1). 用定義好的子類:
NSInvocationOperation 和 NSBlockOperation隆敢。

(2). 繼承NSOperation:
如果你也熟悉Java发皿,NSOperation就和java.lang.Runnable接口很相似。和Java的Runnable一樣筑公,NSOperation也是設(shè)計用來擴展的雳窟,只需繼承重寫NSOperation的一個方法main。相當(dāng)與java 中Runnalbe的Run方法匣屡。然后把NSOperation子類的對象放入NSOperationQueue隊列中封救,該隊列就會啟動并開始處理它。

2>. 例子>.
(1). NSInvocationOperation例子:

- (void)viewDidLoad  
{  
    [super viewDidLoad];  
    NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self   selector:@selector(downloadImage:)  object:kURL];  
      
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];  
    [queue addOperation:operation];  
    // Do any additional setup after loading the view, typically from a nib.  
}  
  
-(void)downloadImage:(NSString *)url{  
    NSLog(@"url:%@", 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;  
} 

(2). 繼承NSOperation:
在.m文件中實現(xiàn)main方法捣作,main方法編寫要執(zhí)行的代碼即可.
3>. 如何控制線程池中的線程數(shù)誉结?
隊列里可以加入很多個NSOperation, 可以把NSOperationQueue看作一個線程池,可往線程池中添加操作(NSOperation)到隊列中券躁。線程池中的線程可看作消費者惩坑,從隊列中取走操作,并執(zhí)行它也拜。
通過下面的代碼設(shè)置:
[queue setMaxConcurrentOperationCount:5];
線程池中的線程數(shù)以舒,也就是并發(fā)操作數(shù)。默認(rèn)情況下是-1慢哈,-1表示沒有限制蔓钟,這樣會同時運行隊列中的全部的操作。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末卵贱,一起剝皮案震驚了整個濱河市滥沫,隨后出現(xiàn)的幾起案子侣集,更是在濱河造成了極大的恐慌,老刑警劉巖兰绣,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件世分,死亡現(xiàn)場離奇詭異,居然都是意外死亡缀辩,警方通過查閱死者的電腦和手機臭埋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來雌澄,“玉大人斋泄,你說我怎么就攤上這事杯瞻「湮” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵魁莉,是天一觀的道長睬涧。 經(jīng)常有香客問我,道長旗唁,這世上最難降的妖魔是什么畦浓? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮检疫,結(jié)果婚禮上讶请,老公的妹妹穿的比我還像新娘。我一直安慰自己屎媳,他們只是感情好夺溢,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著烛谊,像睡著了一般风响。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上丹禀,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天状勤,我揣著相機與錄音,去河邊找鬼双泪。 笑死持搜,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的焙矛。 我是一名探鬼主播葫盼,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼薄扁!你這毒婦竟也來了剪返?” 一聲冷哼從身側(cè)響起废累,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎脱盲,沒想到半個月后邑滨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡钱反,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年掖看,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片面哥。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡哎壳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出尚卫,到底是詐尸還是另有隱情归榕,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布吱涉,位于F島的核電站刹泄,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏怎爵。R本人自食惡果不足惜特石,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鳖链。 院中可真熱鬧姆蘸,春花似錦、人聲如沸芙委。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽题山。三九已至兰粉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間顶瞳,已是汗流浹背玖姑。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留慨菱,地道東北人焰络。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像符喝,于是被迫代替她去往敵國和親闪彼。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容