無忌哥哥跟多線程的情緣

前言:

第一次接觸多線程還是在寫android的時(shí)候,咋一看拍顷,覺得這玩意好難(面試必問)抚太;其實(shí)從字眼上看多線程分為“多”跟“線程”,只要搞明白線程是什么東西昔案,那多線程就迎刃而解了(就是多條線程同時(shí)存在嘛)尿贫,哪線程是什么東西? 我門必須了解一個(gè)非程ごВ基礎(chǔ)的的概念 “進(jìn)程”庆亡,正在進(jìn)行的程序,至于進(jìn)程更多的概念就自行百度吧呼伸! ?

一個(gè)進(jìn)程要想執(zhí)行任務(wù)必須要有線程(線程是進(jìn)程的一條執(zhí)行路徑),每一個(gè)程序至少有一條線程钝尸,進(jìn)程要執(zhí)行的任務(wù)都是放在線程中執(zhí)行的括享,線程的串行,一個(gè)線程中的所有任務(wù)是串行(一個(gè)任務(wù)一個(gè)任務(wù)的執(zhí)行)的珍促,同一時(shí)間一個(gè)線程只能執(zhí)行一個(gè)任務(wù)铃辖;

一個(gè) 進(jìn)程中可以開啟多條線程,每條線程可以并行執(zhí)行不同的任務(wù)猪叙;提高程序的執(zhí)行效率娇斩;

多線程的原理:

同一時(shí)間,CPU 只能處理一條線程穴翩,CPU很快的在多條線程中切換(調(diào)度)犬第,造成了多線程并發(fā)執(zhí)行的原理;? 如果CPU在n多個(gè)線程來回調(diào)度芒帕,會(huì)消耗大量的CPU資源歉嗓; 每條線程被調(diào)度的頻次會(huì)降低;

多線程的優(yōu)點(diǎn):

能適當(dāng)?shù)奶岣叱绦虻膱?zhí)行效率背蟆;能適當(dāng)?shù)奶岣哔Y源利用率鉴分;

多線程的缺點(diǎn):

創(chuàng)建子線程是有開銷的哮幢,主要包括內(nèi)核數(shù)據(jù)結(jié)構(gòu),椫菊洌空間(子線程512k橙垢,主線程1m,也可以使用-setStackSize設(shè)置,必須是4k的倍數(shù))伦糯,創(chuàng)建一個(gè)線程大約是90毫秒的時(shí)間柜某;程序設(shè)計(jì)更加復(fù)雜;多線程之間的數(shù)據(jù)共享舔株;多個(gè)線程同時(shí)占用同一個(gè)資源莺琳;

多線程在IOS中的應(yīng)用?

主線程:默認(rèn)開啟的子線程载慈,叫主線程 也叫 UI線程惭等;

作用: 顯示 刷新 UI,處理UI事件, 不要將比較耗時(shí)的操作放在主線程办铡;

線程的狀態(tài):

內(nèi)存 -》線程對(duì)象(新建狀態(tài))?

調(diào)用 Start -》就緒狀態(tài)(Runable)

CPU 調(diào)度當(dāng)前線程 ?運(yùn)行狀態(tài)(Running)

調(diào)用了sleep 進(jìn)入 阻塞狀態(tài)(Blocked)

正常執(zhí)行 或者 異常退出之后辞做,就會(huì)進(jìn)入死亡狀態(tài)([使用NSThread exit(0)]可以強(qiáng)制殺死線程)

耗時(shí)操作的執(zhí)行:

開啟子線程的的方式:

1. pthread :跨平臺(tái)的線程,使用難度比較大寡具, ?幾乎不用秤茅;(手動(dòng)創(chuàng)建線程,管理線程);

// 示例代碼

pthread_t myRestrict;

pthread_create(&myRestrict, NULL, run, NULL);

void *run(void *data)

{

for (int i=0; i<1000000; i++) {

NSLog(@"%d",i);

}

NSLog(@"run----&@",[NSThread currentThread]);

return NULL;

}

2. NSThread : 面向?qū)ο笸?jiǎn)單易用框喳,可是直接操作線程對(duì)象, 偶爾使用厦坛,使用 NSThread管理多個(gè)線程非常困難五垮;

(1) [NSThread currentThread] //跟蹤任務(wù)所在線程,適用于這三種技術(shù).

(2) [NSThread sleepForTimeInterval:] //睡眠多長(zhǎng)時(shí)間(秒)

/**

*? 創(chuàng)建線程的方式1

*/

- (void)createThread1

{

// 1.初始化

NSThread *thread=[[NSThread alloc]initWithTarget:self selector:@selector(download) object:nil];

thread.name=@"線程2號(hào)";

//啟動(dòng)線程

[thread start];

//獲取主線程

[NSThread mainThread];

}

/**

*? 創(chuàng)建線程的方式2,? 直接創(chuàng)建

*/

- (void)createThread2

{

// 分離 ,派遣

[NSThread detachNewThreadSelector:@selector(download:) toTarget:self withObject:@"www.baidu.com"];

}

/**

*? 創(chuàng)建線程的方式3,? 隱身創(chuàng)建線程

*/

- (void)createThread3

{

[self performSelectorInBackground:@selector(download:) withObject:self];

}

/**

*? 創(chuàng)建線程的方式4,? 隱身創(chuàng)建線程

*/

- (void)createThread4

{

[self performSelector:@selector(download:) onThread:[NSThread mainThread] withObject:self waitUntilDone:YES];}

3. GCD:(Grand Central Dispatch),偉大的中樞調(diào)度器杜秸,取代NSThread,充分利用設(shè)備的多核并行運(yùn)算放仗;線程的生命周期是自動(dòng)管理的,經(jīng)常使用撬碟;

GCD的核心概念:任務(wù)(執(zhí)行什么操作) 跟 隊(duì)列(用來存放任務(wù)诞挨,相當(dāng)于線程池)

3.1 任務(wù)執(zhí)行方式: 同步或者異步執(zhí)行

//同步執(zhí)行

dispatch_async(<#dispatch_queue_t queue#>, <#^(void)block#>)

//異步執(zhí)行

dispatch_sync(<#dispatch_queue_t queue#>, <#^(void)block#>)

3.2 隊(duì)列:并發(fā)隊(duì)列(concurrent),可以讓多個(gè)任務(wù)并發(fā)執(zhí)行呢蛤,并發(fā)功能只有在dispatch_async才有效惶傻,蘋果提供了DISPATCH_QUEUE_PRIORITY_DEFAULT ,使用dispatch_get_global_queue獲取就好了其障;

異步執(zhí)行是在執(zhí)行函數(shù)完成之后达罗,在返回去開辟子線程;

串行隊(duì)列,一個(gè)任務(wù)一個(gè)任務(wù)的執(zhí)行粮揉,主隊(duì)列

同步和異步主要區(qū)別:能不能開啟新的線程

同步:只能在當(dāng)前線程中執(zhí)行任務(wù)巡李,不具備開啟新線程的能力

異步:可以在新的線程中執(zhí)行任務(wù),有開啟新線程的能力

并發(fā)和串行的主要區(qū)別:任務(wù)的執(zhí)行方式

并發(fā):允許多個(gè)任務(wù)同時(shí)執(zhí)行

串行:一個(gè)任務(wù)執(zhí)行完畢之后在執(zhí)行下一個(gè)任務(wù)

排列組合共有四種方式:

/**

*? 異步的+全局隊(duì)列? 最常用

*/

- (void)asyncGlobalQueue

{

dispatch_queue_t queue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_async(queue, ^{

NSLog(@"1---%@",[NSThread currentThread]);

});

dispatch_async(queue, ^{

NSLog(@"2---%@",[NSThread currentThread]);

});

dispatch_async(queue, ^{

NSLog(@"3---%@",[NSThread currentThread]);

});

}

/**

*? 同步+并行隊(duì)列

*/

- (void)syncGlobalQueue

{

dispatch_queue_t queue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_sync(queue, ^{

NSLog(@"1---%@",[NSThread currentThread]);

});

dispatch_sync(queue, ^{

NSLog(@"2---%@",[NSThread currentThread]);

});

dispatch_sync(queue, ^{

NSLog(@"3---%@",[NSThread currentThread]);

});

}

/**

*? 異步的串行隊(duì)列,? 一個(gè)一個(gè)按順序執(zhí)行

*/

- (void)asyncSerialQueue

{

dispatch_queue_t queue=dispatch_queue_create("com.zhangkun", NULL);

dispatch_async(queue, ^{

NSLog(@"1---%@",[NSThread currentThread]);

});

dispatch_async(queue, ^{

NSLog(@"2---%@",[NSThread currentThread]);

});

dispatch_async(queue, ^{

NSLog(@"3---%@",[NSThread currentThread]);

});

}

/**

*? 同步的串行隊(duì)列,? 一個(gè)一個(gè)按順序執(zhí)行

在主獻(xiàn)

*/

- (void)syncSerialQueue

{

dispatch_queue_t queue=dispatch_queue_create("com.zhangkun", NULL);

dispatch_sync(queue, ^{

NSLog(@"1---%@",[NSThread currentThread]);

});

dispatch_sync(queue, ^{

NSLog(@"2---%@",[NSThread currentThread]);

});

dispatch_sync(queue, ^{

NSLog(@"3---%@",[NSThread currentThread]);

});

}

GCD線程之間的通信:

// 返回主線程

dispatch_sync(dispatch_get_main_queue(), <#^(void)block#>)

self performSelectorOnMainThread:<#(nonnull SEL)#> withObject:<#(nullable id)#> waitUntilDone:<#(BOOL)#>

GCD常用的函數(shù):

// 在前面的任務(wù)執(zhí)行結(jié)束后 它才執(zhí)行扶认,而且它后面的任務(wù)等它執(zhí)行完成之后才會(huì)執(zhí)行

dispatch_barrier_async(<#dispatch_queue_t queue#>, <#^(void)block#>)

// 延遲執(zhí)行

[self performSelector:@selector(run) withObject:param afterDelay:3];

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

NSLog(@"----2秒之后執(zhí)行");

});

[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:NO];

// 整個(gè)程序運(yùn)行過程中只執(zhí)行一次侨拦, 跟懶加載不同 ?(一次性代碼)

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

NSLog(@"只會(huì)執(zhí)行一次,資源加載 ? 線程安全的");

});

// 遍歷線程

dispatch_apply(10, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t) {

});

GCD隊(duì)列小案例:

//1. 隊(duì)列組

dispatch_group_t group = dispatch_group_create();

//2.

__block UIImage *image = nil;

__block UIImage *image1 = nil;

dispatch_group_async(group, kGlobalQueue, ^{

//下載一張·圖片

NSURL *url= [NSURL URLWithString:@"http://img5.iqilu.com/c/u/2015/0811/1439259819581.jpg"];

NSData *data=[NSData dataWithContentsOfURL:url];

image=[UIImage imageWithData:data];

});

dispatch_group_async(group, kGlobalQueue, ^{

//下載第二張圖片

NSURL *url1= [NSURL URLWithString:@"https://www.baidu.com/img/bd_logo1.png"];

NSData *data1=[NSData dataWithContentsOfURL:url1 ];

image1=[UIImage imageWithData:data1];

});

//保證組里邊的事情都執(zhí)行完辐宾, 才執(zhí)行block塊

dispatch_group_notify(group, kGlobalQueue, ^{

//合并圖片? 搞一張大的圖片狱从, 然后把第一張圖片畫上去

//開啟圖片上下文

UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);

[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];

[image1 drawInRect:CGRectMake(0, 0, image1.size.width*0.5, image1.size.height*0.5)];

//繪制完畢,得到上文的圖片

UIImage *imageC= UIGraphicsGetImageFromCurrentImageContext();

//結(jié)束圖片上下文

UIGraphicsEndImageContext();

//回到主線程設(shè)置圖片

dispatch_async(kMainQueue, ^{

NSLog(@"%@",[NSThread currentThread]);

[self.img setImage:imageC];

});

});

使用GCD實(shí)現(xiàn)單例模式(設(shè)計(jì)模式叠纹,保證在程序運(yùn)行的過程中一個(gè)類只有一個(gè)實(shí)例季研, 在整個(gè)應(yīng)用程序中要共享同一份資源)

實(shí)現(xiàn)方式(想辦法讓對(duì)象的內(nèi)存空間只存在一份, 也可以在load中初始化誉察,也可以使用@synchronized与涡,這里就演示了);

/**

*? alloc 內(nèi)部會(huì)調(diào)用這個(gè)方法

*/

+(instancetype)allocWithZone:(struct _NSZone *)zone

{

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

_instance = [super allocWithZone:zone];

});

return _instance;

}

+ (instancetype)shareStudentTool

{

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

_instance = [[self alloc]init];//防止創(chuàng)建多次

});

return _instance;

}

-(id)copyWithZone:(NSZone *)zone

{

return _instance;

}

在 pch中使用:

//.h

#define kSingH(name) + (instancetype)shareTool##name;

//.m

#define kSingM(name) ?static id _instance;\

+(instancetype)allocWithZone:(struct _NSZone *)zone\

{\

static dispatch_once_t onceToken;\

dispatch_once(&onceToken, ^{\

_instance=[super allocWithZone:zone];\

});\

return _instance;\

}\

+ (instancetype)shareTool##name\

{\

static dispatch_once_t onceToken;\

dispatch_once(&onceToken, ^{\

_instance=[[self alloc]init];\

});\

return _instance;\

}\

-(id)copyWithZone:(NSZone *)zone\

{\

return _instance;\

\

}

以后想使用單例直接在.h .m 中調(diào)用定義好的宏就好了持偏,是不是很簡(jiǎn)單驼卖;

NSOperation:基于GCD的,對(duì)GCD的一層封裝鸿秆,自動(dòng)管理酌畜;

多線程的安全隱患:

NSOperation 跟 NSOperationQueue

NSOperation 并不具備封裝任務(wù)的能力,使用NSOperation子類有三種:

NSInvocationOperation

NSOperationQueue *queue = [[NSOperationQueue alloc]init];

NSInvocationOperation *invo = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download) object:nil];

//operation 調(diào)用start卿叽,是同步執(zhí)行

[invo start];

//只有將操作放在隊(duì)列中桥胞,才會(huì)異步執(zhí)行

[queue addOperation:invo];

NSBlockOperation

自定義子類繼承NSOperation

NSOperationQueue : 并發(fā)隊(duì)列 / 串行隊(duì)列

+ (nullable NSOperationQueue *)currentQueue NS_AVAILABLE(10_6, 4_0);

+ (NSOperationQueue *)mainQueue NS_AVAILABLE(10_6, 4_0);

// 主隊(duì)列

[NSOperationQueue mainQueue];

// 同時(shí)包含了:串行? 并發(fā) 的功能? ,就會(huì)自動(dòng)放到子線程中

NSOperationQueue *queque = [[NSOperationQueue alloc]init];

NSOperationQueue 的掛起和取消 (suspended):

[queue cancelAllOperations];//取消隊(duì)列中的任務(wù)

[queue setSuspended:YES];//暫停隊(duì)列中的任務(wù)

[queue setSuspended:NO];// 恢復(fù)隊(duì)列中的任務(wù)

addDependency : 依賴

//假如有ABC三個(gè)操作考婴, 要求贩虾, 三個(gè)操作 異步執(zhí)行

NSOperationQueue *queue=[[NSOperationQueue alloc]init];

NSBlockOperation *operaA=[NSBlockOperation blockOperationWithBlock:^{

NSLog(@"1%@",[NSThread currentThread]);

}];

[operaA? setCompletionBlock:^{

NSLog(@"1%@",[NSThread currentThread]);

}];

NSBlockOperation *operaB=[NSBlockOperation blockOperationWithBlock:^{

NSLog(@"2%@",[NSThread currentThread]);

}];

NSBlockOperation *operaC=[NSBlockOperation blockOperationWithBlock:^{

NSLog(@"4%@",[NSThread currentThread]);

}];

[operaB addDependency:operaA];

[operaC addDependency:operaB];

[queue addOperation:operaA];

[queue addOperation:operaB];

[queue addOperation:operaC];

?資源共享: 一塊資源可能會(huì)被多個(gè)線程共享,也就是多個(gè)線程可能會(huì)訪問同一塊兒資源蕉扮;

比如多個(gè)線程同時(shí)訪問 同一個(gè)對(duì)象 ?同一個(gè)變量 ?同一個(gè)文件整胃;

老生常談的demo:

1.存取錢颗圣, 多個(gè)任務(wù)在多條線程同時(shí)執(zhí)行存取錢的任務(wù)喳钟;

2.賣票, 多個(gè)窗口同時(shí)在賣票在岂,先查詢票數(shù)夠不夠奔则,出現(xiàn)一張票被多個(gè)人買走的問題;

解決方案: 加互斥鎖 蔽午,線程同步

優(yōu)點(diǎn):能有效的防治因多線程搶奪資源造成的數(shù)據(jù)安全隱患 ?(互斥鎖的應(yīng)用場(chǎng)景)

缺點(diǎn):需要消耗大量的CPU資源

使用@synchronized將要鎖的代碼{}起來

while (1) {

@synchronized(self){//開始加鎖

int count = self.lastSale;

if (count > 0) {

self.lastSale = count-1;

[NSThread sleepForTimeInterval:0.1];

NSLog(@"%@---%d",[NSThread currentThread].name,count);

}else{return;}

補(bǔ)充: 原子跟非原子屬性

atomic: 原子屬性易茬,為setter方法加鎖 (默認(rèn)是atomic), 消耗大量的資源

nonatomic: 非原子屬性,不會(huì)加鎖抽莱, iOS開發(fā)建議 都聲明為nonatomic

線程之間的通信:

1.圖片下載

主線程添加UIImageView,子線程下載圖片范抓,在回到主線程渲染圖片;

2.NSPort ?NSMessagePort NSMachPort ?可以在線程之間進(jìn)行通信

主線程(port:8080) 傳子線程(port:8181)

事件處理

Runtime

Runloop : 既能保住線程的命食铐, 就能讓線程繼續(xù)工作匕垫;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市虐呻,隨后出現(xiàn)的幾起案子象泵,更是在濱河造成了極大的恐慌,老刑警劉巖斟叼,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件偶惠,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡朗涩,警方通過查閱死者的電腦和手機(jī)忽孽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來馋缅,“玉大人扒腕,你說我怎么就攤上這事∮┿玻” “怎么了瘾腰?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)覆履。 經(jīng)常有香客問我蹋盆,道長(zhǎng),這世上最難降的妖魔是什么硝全? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任栖雾,我火速辦了婚禮,結(jié)果婚禮上伟众,老公的妹妹穿的比我還像新娘析藕。我一直安慰自己,他們只是感情好凳厢,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布账胧。 她就那樣靜靜地躺著,像睡著了一般先紫。 火紅的嫁衣襯著肌膚如雪治泥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天遮精,我揣著相機(jī)與錄音居夹,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛准脂,可吹牛的內(nèi)容都是我干的劫扒。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼狸膏,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼粟关!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起环戈,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤闷板,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后院塞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體遮晚,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年拦止,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了县遣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡汹族,死狀恐怖萧求,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情顶瞒,我是刑警寧澤夸政,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站榴徐,受9級(jí)特大地震影響守问,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜坑资,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一耗帕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧袱贮,春花似錦仿便、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至窑业,卻和暖如春钦幔,著一層夾襖步出監(jiān)牢的瞬間枕屉,已是汗流浹背常柄。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人西潘。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓卷玉,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親喷市。 傳聞我的和親對(duì)象是個(gè)殘疾皇子相种,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

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

  • NSThread 第一種:通過NSThread的對(duì)象方法 NSThread *thread = [[NSThrea...
    攻城獅GG閱讀 789評(píng)論 0 3
  • 在這篇文章中,我將為你整理一下 iOS 開發(fā)中幾種多線程方案品姓,以及其使用方法和注意事項(xiàng)寝并。當(dāng)然也會(huì)給出幾種多線程的案...
    張戰(zhàn)威ican閱讀 601評(píng)論 0 0
  • 歡迎大家指出文章中需要改正或者需要補(bǔ)充的地方,我會(huì)及時(shí)更新腹备,非常感謝衬潦。 一. 多線程基礎(chǔ) 1. 進(jìn)程 進(jìn)程是指在系...
    xx_cc閱讀 7,171評(píng)論 11 70
  • 在這篇文章中镀岛,我將為你整理一下 iOS 開發(fā)中幾種多線程方案,以及其使用方法和注意事項(xiàng)友驮。當(dāng)然也會(huì)給出幾種多線程的案...
    伯恩的遺產(chǎn)閱讀 274,350評(píng)論 251 2,331
  • CABasicAnimation 父類是CAPropertyAnimation CABasicAnimation—...
    翻這個(gè)墻閱讀 293評(píng)論 0 0