日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

iOS学习之多线程

發(fā)布時間:2024/1/18 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iOS学习之多线程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.


在iOS中提供了4中多線程的方式

以下4中方式:

pthread使用較少



pthread? 這是一套通用的多線程api,適用于linux、UNIX、windows 等系統(tǒng) ?跨平臺技術(shù),可移植 純c語言
? ? ?NSThread *current = [NSThread currentThread];
1、創(chuàng)建一個線程id
pthread_t threadId; pthrad_create(&threadId,NULL,run,NULL);
void *run(void *data) { ? ? ?return NULL; }

NSThread 一個NSThread對象就代表一條線程 使用更加面向?qū)ο?#xff0c;可以直接操作線程對象,oc 語言 ? 程序員進行管理 線程的生命周期
主線程相關(guān)用法 NSThread *current = [NSThread currentThread]; NSThread *mainThread = [NS] 判斷是不是主線程 [NSThread isMainThread];
線程的優(yōu)先級 NSThread?threadPriority -(BOOL)setThreadPriority:(double); 調(diào)度優(yōu)先級的取值范圍是0.0 — 1.0 值越大 優(yōu)先級越高


1、創(chuàng)建線程 *1 NSThread *thread = [[ NSThread alloc ] initWithTarget : self? selector : @selector (run:) object : @"aaa" ]; // 開啟線程 [thread start];
*2 創(chuàng)建后就執(zhí)行 ?自動啟動 無法對線程進行更詳細的設(shè)置 [NSThread detachNewThreadS elector : @selector (run:) object : @"aaa" ]; ]
3*// 隱式創(chuàng)建 [self performSelectorInBackground:@selector(run:)withObject:@"aa"];
-(void)run { ?????
}
線程的生命周期 新建——————》線程對象進入可調(diào)度線程池(就緒狀態(tài))——————》運行狀態(tài)(如果cpu調(diào)度當前線程)——————》調(diào)用sleep方法?當前線程從調(diào)度池 ,但是該線程仍然在內(nèi)存中?—————》當阻塞結(jié)束 當前進程進入就緒狀態(tài)
線程任務(wù)執(zhí)行完畢、異常退出、強制退出 ?都是 線程進入死亡狀態(tài)(仍然在內(nèi)存中) //阻塞線程 +(void)sleepUntiData:(NSDate:)date; + ? (void)sleepForTimeInterval:(NSTimeInterval)ti; 強制停止線程 +(void)exit; ? 線程進入死亡狀態(tài)

線程加鎖(線程同步)—》多條線程按順序的執(zhí)行任務(wù) ?互斥鎖 就是使用了線程同步技術(shù) NSLock *lock = [[NSLock alloc]init]; 線程讀之前加鎖(只能用一把鎖)


? @synchronized(self){ 加鎖 ? ? ?大括號內(nèi)的代碼有線程安全問題代碼要進行加鎖操作

}大括號結(jié)束解鎖

線程間通信 兩個進行線程間通信的方法 下面方法在主線程中執(zhí)行 settingImage 方法 [self performSelectorOnMainThread:@selector(settingImage:) withObject:image waitUntilDone:NO];
下面方法是在 onThread指定的線程中執(zhí)行某個方法 [self performSelector:<#(SEL)#> onThread:<#(NSThread *)#> withObject:<#(id)#> waitUntilDone:<#(BOOL)#> modes:<#(NSArray *)#>]

對ui界面的操作要在主線程中執(zhí)行,例如以下載圖片為例可以使用 下面方法的意思是:在主線程中調(diào)用imageView 的 setImage:方法將imageView的image設(shè)置為 下載好的image 其中 waitUntilDone設(shè)置為NO為 調(diào)用完這個方法會立即返回? ? ?waitUntilDone設(shè)置為YES 這個方法會在主線程執(zhí)行完setImage:方法后返回 [self.imageView performSelector:@selector(setImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:NO];
[ self . imageView performSelectorOnMainThread : @selector (setImage:) withObject :image waitUntilDone : NO ];




GCD???? Grand Central Dispatch? 牛逼的中樞調(diào)度器

優(yōu)勢: 1、多核的并行運算提出的解決方案 2、會自動利用更多的cpu內(nèi)核 3、自動關(guān)了線程的生命周期(創(chuàng)建線程、調(diào)度任務(wù)、銷毀線程) 4、不需要編寫任何線程管理代碼 ? 只需要告訴GCD 要執(zhí)行的任務(wù) ?GCD 會自動創(chuàng)建隊列執(zhí)行任務(wù)
使用:兩個步驟 ? 定制任務(wù) ? 添加定制任務(wù)到隊列中 —》 GCD會自動將隊列中的任務(wù)取出,放到對應(yīng)的線程中執(zhí)行 任務(wù)的取出遵循 FIFO ?先進先出

//凡是函數(shù)名種帶有create\copy\new\retain等字眼,都需要在不需要使用這個數(shù)據(jù)的時候進行release
// GCD的數(shù)據(jù)類型在ARC環(huán)境下不需要再做release
// CF(Core Foundation) 的數(shù)據(jù)類型在 ARC 環(huán)境下還是需要再做 release


/**
?*?
全局并發(fā)隊列
?*/

#define global_queue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 )
/**
?*?
主隊列
?*/
#define main_queue dispatch_get_main_queue()

基本使用:(同步函數(shù)和異步函數(shù)———決定了要不要開啟新的線程) 1、2個用來執(zhí)行任務(wù)的函數(shù) 同步:在當前線程中執(zhí)行任務(wù) 不具備開啟新線程的能力 dispatch_sync(<#dispatch_queue_t queue#>, <#^(void)block#>)
異步:在另一條線程中執(zhí)行 ?具備了開啟新線程的能力 dispatch_async(<#dispatch_queue_t queue#>, <#^(void)block#>)
特殊情況:異步函數(shù)的任務(wù)添加在主隊列中(往主隊列中添加一個同步任務(wù)), 任務(wù)在主線程執(zhí)行,不會開啟新的線程
2、隊列 分為兩大類(并發(fā)和串行————決定了任務(wù)的執(zhí)行方式) 并發(fā)隊列:可以讓多個任務(wù)并發(fā)同時執(zhí)行(自動開啟多條線程) ? 在異步函數(shù)中執(zhí)行
串行隊列:讓任務(wù)一個接著一個執(zhí)行
并發(fā)隊列:GCD默認已經(jīng)提供了全局的并發(fā)隊列供整應(yīng)用程序使用,不需要手動創(chuàng)建

獲取一個全局的默認優(yōu)先級的并發(fā)隊列 dispatch_queue_tqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
添加任務(wù)到隊列中執(zhí)行任務(wù)
1、 dispatch_async 異步函數(shù)往并發(fā)隊列中添加任務(wù)—————》同時開啟了3個子線程 - (void)asyncGlobalQueue
{
???//?獲取一個全局的默認優(yōu)先級的并發(fā)隊列 ???dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
???
???
// 2.添加任務(wù)到隊列中執(zhí)行
???
dispatch_async(queue, ^{
???????
NSLog(@"----下載圖片1-----%@", [NSThreadcurrentThread]);
??? });
???
dispatch_async(queue, ^{
???????
NSLog(@"----下載圖片2-----%@", [NSThreadcurrentThread]);
??? });
???
dispatch_async(queue, ^{
???????
NSLog(@"----下載圖片3-----%@", [NSThreadcurrentThread]);
??? }); ???// 總結(jié):同時開啟了3個線程 }
2、用dispatch_async異步函數(shù) 往串行隊列中添加任務(wù)————————》只開了一個線程執(zhí)行任務(wù) - (void)asyncSerialQueue {
???
// 1.創(chuàng)建串行隊列
???
dispatch_queue_t queue = dispatch_queue_create("com.itheima.queue",NULL);
???
???
// 2.添加任務(wù)到隊列中執(zhí)行
???
dispatch_async(queue, ^{
???????
NSLog(@"----下載圖片1-----%@", [NSThreadcurrentThread]);
??? });
???
dispatch_async(queue, ^{
???????
NSLog(@"----下載圖片2-----%@", [NSThreadcurrentThread]);
??? });
???
dispatch_async(queue, ^{
???????
NSLog(@"----下載圖片3-----%@", [NSThreadcurrentThread
]);
??? });
? ?//總結(jié):只開1個線程執(zhí)行任務(wù) }

3、用dispatch_sync同步函數(shù)往并發(fā)隊列中添加任務(wù)—————》不會開啟新的線程,并發(fā)隊列失去了并發(fā)的功能 - (void)syncGlobalQueue
{
???
// 1.獲得全局的并發(fā)隊列
???
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
???
???
// 2.添加任務(wù)到隊列中執(zhí)行
???
dispatch_sync(queue, ^{
???????
NSLog(@"----下載圖片1-----%@", [NSThreadcurrentThread]);
??? });
???
dispatch_sync(queue, ^{
???????
NSLog(@"----下載圖片2-----%@", [NSThreadcurrentThread]);
??? });
???
dispatch_sync(queue, ^{
???????
NSLog(@"----下載圖片3-----%@", [NSThreadcurrentThread]);
??? });
???
???
// 總結(jié):不會開啟新的線程,并發(fā)隊列失去了并發(fā)的功能
}

4、 dispatch_sync 同步函數(shù)往串行列中添加任務(wù)—————》不會開啟新的線程 - (void)syncSerialQueue
{
???// 1.創(chuàng)建串行隊列(串行隊列) ???dispatch_queue_t queue = dispatch_queue_create("com.itheima.queue",NULL);
???
???
// 2.添加任務(wù)到隊列中執(zhí)行
???
dispatch_sync(queue, ^{
???????
NSLog(@"----下載圖片1-----%@", [NSThreadcurrentThread]);
??? });
???
dispatch_sync(queue, ^{
???????
NSLog(@"----下載圖片2-----%@", [NSThreadcurrentThread]);
??? });
???
dispatch_sync(queue, ^{
???????
NSLog(@"----下載圖片3-----%@", [NSThreadcurrentThread]);
??? });
???
???
// 3.釋放資源
//??? dispatch_release(queue); ? // MRC(ARC)
???
???
// 總結(jié):不會開啟新的線程
}




5、 dispatch_sync 同步函數(shù) , 在主線程中往主隊列中添加任務(wù) : 任務(wù)無法往下執(zhí)行———————>產(chǎn)生死鎖(死循環(huán)) - (void)syncMainQueue
{
???
// 1.獲得主隊列
???
dispatch_queue_t queue = dispatch_get_main_queue();
???
???// 2.添加任務(wù)到隊列中執(zhí)行 ?????(queue, ^{ ???????NSLog(@"----下載圖片1-----%@", [NSThreadcurrentThread]);
??? });
//??? dispatch_sync(queue, ^{
//??????? NSLog(@"----下載圖片2-----%@", [NSThread currentThread]);
//??? });
//??? dispatch_sync(queue, ^{
//??????? NSLog(@"----下載圖片3-----%@", [NSThread currentThread]);
//??? });

}
6、 使用dispatch_async異步函數(shù),在主線程中往主隊列中添加任務(wù) 特殊情況:異步函數(shù)的任務(wù)添加在主隊列中(往主隊列中添加一個同步任務(wù)), 任務(wù)在主線程執(zhí)行,不會開啟新的線程
- ( void )asyncMainQueue { ??? // 1.獲得主隊列(串行隊列) ??? dispatch_queue_t queue = dispatch_get_main_queue ();
???
???
// 2. 添加任務(wù)到隊列中 執(zhí)行
???
dispatch_async (queue, ^{
???????
NSLog ( @"---- 下載圖片 1-----%@" , [ NSThread currentThread ]);
??? });
}

同步函數(shù)(sync) 并發(fā)隊列:不會開啟線程 串行隊列:不會開啟線程 異步函數(shù)(async) 并發(fā)隊列:開啟多個線程 串行隊列:開啟一條線程

使用GCD進行異步圖片下載 1、獲取全局并發(fā)隊列 ??? dispatch_queue_tqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0); 2、調(diào)用異步(同步)函數(shù)下載圖片 dispatch_async(queue, ^{//開啟異步線程下載圖片 ???????NSLog(@"當前線程%@",[NSThreadcurrentThread]);
???????
NSURL *url = [NSURLURLWithString:@"http://www.res.meizu.com/resources/www_image/weixin.jpg"];
???????
NSData *data = [NSDatadataWithContentsOfURL:url];
???????
???????
UIImage *image = [UIImageimageWithData:data];
? ? ?? 3、回到主隊列刷新圖片 ???????dispatch_async(dispatch_get_main_queue(), ^{
???????????
self.imageView.image= image;
??????? });
??? });

GCD的其他用法
1、延遲執(zhí)行? *1 ?[self performSelector:@selector(run) withObject:nil afterDelay:2.0];
*2 利用GCD 進行延遲執(zhí)行(推薦) dispatch_queue_t queue =? dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //??? /**
// ??? *? 2 秒鐘后 ? 在隊列 queue 中執(zhí)行 block 中的任務(wù)
// ??? */
//??? dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), queue, ^{
//??? //??? });

2、一次性代碼 ? 使某一段代碼在整個程序運行過程中只執(zhí)行一次,用于創(chuàng)建單? dispatch_once static id _instance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ ??????_instance = [[self alloc]init]; });
3、隊列組 ?當程序需要執(zhí)行完多個耗時操作后 在執(zhí)行某個其他操作的時候使用 如:下載兩張圖片 ?下載完成后進行拼接顯示在imageView上 *1、?創(chuàng)建一個組 dispatch_group_t group = dispatch_group_create(); *2、開啟一個任務(wù)下載圖片1 __block? UIImage *image1 = nil;
???
//開啟一個任務(wù)下載圖片1
???
dispatch_group_async(group, global_queue, ^{
??????? image1 = [
self imageWithUrl:@"1"];
??? }); *3?開啟一個任務(wù)下載圖片2 ?? __block UIImage *image2 = nil;
???
//開啟一個任務(wù)下載圖片2
??? dispatch_group_async(group, global_queue, ^{ ? ? image2 = [self imageWithUrl:@"2"]; ??? }); 4* 等待group中的所有任務(wù)都執(zhí)行完畢后 ?在執(zhí)行其他操作 ??? dispatch_group_notify(group, main_queue, ^{ // 合并圖 ?????UIGraphicsBeginImageContextWithOptions(CGSizeMake(200, 100), NO, 0.0); ?????[image1 drawInRect:CGRectMake(0, 0, 100, 100)]; ?????[image2 drawInRect:CGRectMake(100, 0, 100, 100)]; ?????UIImageView *imageView = nil; ?????imageView.image = UIGraphicsGetImageFromCurrentImageContext(); ?? ??? });





NSOperation

使用NSOperation 的子類 創(chuàng)建任務(wù) ? NSInvocationOperation 、?NSBlockOperation
1、封裝任務(wù) ???NSInvocationOperation *opration1 = [[NSInvocationOperationalloc]initWithTarget:selfselector:@selector(download)object:nil];
???NSInvocationOperation *opration2 = [[NSInvocationOperationalloc]initWithTarget:selfselector:@selector(run)object:nil];
??? NSBlockOperation *blockOperation = [ NSBlockOperation blockOperationWithBlock :^{
??????
NSLog ( @"%@——1----" ,[ NSThread currentThread ]); ??? }];
??? [ blockOperation addExecutionBlock:^{
???????
NSLog ( @"%@—2-------" ,[ NSThread currentThread ]); ??? }];
以上有三個操作( opration1、 opration2、 blockOperation ) ?4個任務(wù)( download、 run、 %@——1—— %@——2----
2、創(chuàng)建隊列
NSOperationQueue*queue = [[NSOperationQueuealloc]init];
// 最大并發(fā)數(shù) ? 同一時間只能做 2 件事 ? 控制開線程的個數(shù) ?queue.maxConcurrentOperationCount= 2;//2---3
// 任務(wù)在隊列中的優(yōu)先級 ???/*
???? NSOperationQueuePriorityVeryLow = -8L,
???? NSOperationQueuePriorityLow = -4L,
???? NSOperationQueuePriorityNormal = 0,
???? NSOperationQueuePriorityHigh = 4,
???? NSOperationQueuePriorityVeryHigh = 8
???? */ opration1.queuePriority= NSOperationQueuePriorityNormal;
操作依賴 // 操作依賴 ? 在添加到隊列之前 ? ---- 可以再不同隊列間的 operation 之間添加依賴 ? 不能相互依賴 //opration1依賴 opration2? opration2執(zhí)行完畢后才能?執(zhí)行opration1 ??? [opration1addDependency:opration2];
??? // 操作的監(jiān)聽
???
// blockOperation 中的操作完成后 在當前線程中執(zhí)行下面操作
??? blockOperation.
completionBlock= ^{

??? };
//添加到隊列中---------》異步執(zhí)行???多個任務(wù)一定是并行操作[queueaddOperation:opration1]; [queueaddOperation:opration2]; [queueaddOperation:blockOperation];


自定義NSOperation
創(chuàng)建屬性 /**
?*?
下載圖片的隊列
?*/

@property(nonatomic,strong)NSOperationQueue *queue;
/** key:url value:operation對象*/
@property(nonatomic,strong)NSMutableDictionary *operations; /** key:url value:image對象*/ @property(nonatomic,strong)NSMutableDictionary *images;
懶加載 - (NSArray*)apps
{
???
if (!_apps) {
???????
NSArray *dictArray = [NSArrayarrayWithContentsOfFile:[[NSBundlemainBundle]pathForResource:@"apps.plist"ofType:nil]];
???????
???????
NSMutableArray *appArray = [NSMutableArrayarray];
???????
for (NSDictionary*dict in dictArray) {
???????????
HMApp *app = [HMAppappWithDict:dict];
??????????? [appArray
addObject:app];
??????? }
???????
_apps = appArray;
??? }
???
return _apps;
}

- (
NSOperationQueue*)queue
{
???
if (!_queue) {
???????
_queue = [[NSOperationQueuealloc]init];
???????
_queue.maxConcurrentOperationCount= 3;// 最大并發(fā)數(shù) == 3
??? }
???
return _queue;
}

- (
NSMutableDictionary*)operations
{
???
if (!_operations) {
???????
_operations = [NSMutableDictionarydictionary];
??? }
???
return _operations;
}

- (
NSMutableDictionary*)images
{
???
if (!_images) {
???????
_images = [NSMutableDictionarydictionary];
??? }
???
return _images;
}


cell中下載圖片的代碼 //顯示圖片
???
// 保證一個url對應(yīng)一個HMDownloadOperation
???
// 保證一個url對應(yīng)UIImage對象
???
???
UIImage *image = self.images[app.icon];
???
if (image) { //?內(nèi)存緩存中有圖片
??????? cell.
imageView.image= image;
??? }
else { //?內(nèi)存緩存中沒有圖片,得下載
//??????? cell.imageView.image = [UIImage imageNamed:@"57437179_42489b0"];
???????
???????
HMDownloadOperation *operation = self.operations[app.icon];
???????
if (operation) { // 正在下載
???????????
// ... 暫時不需要做其他事
???????????
??????? }
else { // 沒有正在下載
???????????
// 創(chuàng)建操作
??????????? operation = [[
HMDownloadOperationalloc]init];
??????????? operation.
url= app.icon;
??????????? operation.
delegate= self;
??????????? operation.
indexPath= indexPath;
??????????? [
self.queueaddOperation:operation];// 異步下載
???????????
???????????
self.operations[app.icon] = operation;
??????? }
??? }
#pragma mark - HMDownloadOperationDelegate
- ( void )downloadOperation:( HMDownloadOperation *)operation didFinishDownload:( UIImage *)image
{
???
// 1. 移除執(zhí)行完畢的操作
??? [
self . operations removeObjectForKey :operation. url ];
???
???
if (image) {
???????
// 2. 將圖片放到緩存中 (images)
???????
self . images [operation. url ] = image;
???????
???????
// 3. 刷新表格
??????? [
self . tableView reloadRowsAtIndexPaths : @[ operation. indexPath ] withRowAnimation : UITableViewRowAnimationNone ];
???????
???????
// 3. 將圖片寫入沙盒
//??????? NSData *data = UIImagePNGRepresentation(image);
//??????? [data writeToFile:@"" atomically:<#(BOOL)#>];
??? }
???
}
tableView滾動的時候的操作 - (void)scrollViewWillBeginDragging:(UIScrollView*)scrollView
{
???
// 開始拖拽
???
// 暫停隊列
??? [
self.queuesetSuspended:YES];
}

- (
void)scrollViewWillEndDragging:(UIScrollView*)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inoutCGPoint *)targetContentOffset
{
??? [
self.queuesetSuspended:NO];
}


自定義NSOperation的代碼 HMDownloadOperation.h @classHMDownloadOperation;

@protocolHMDownloadOperationDelegate <NSObject>
@optional
- (
void)downloadOperation:(HMDownloadOperation*)operation didFinishDownload:(UIImage*)image;
@end

@interfaceHMDownloadOperation : NSOperation
@property(nonatomic,copy)NSString *url;
@property(nonatomic,strong)NSIndexPath *indexPath;
@property(nonatomic,weak)id<HMDownloadOperationDelegate> delegate;
@end

HMDownloadOperation.m /**
?*?
main方法中實現(xiàn)具體操作
?*/

- (
void)main
{
???
@autoreleasepool {
???????
if (self.isCancelled)return;
???????
???????
NSURL *downloadUrl = [NSURLURLWithString:self.url];
???????
NSData *data = [NSDatadataWithContentsOfURL:downloadUrl];// 這行會比較耗時
???????
???????
if (self.isCancelled)return;
???????
???????
UIImage *image = [UIImageimageWithData:data];
???????
???????
if (self.isCancelled)return;
???????
???????
if ([self.delegaterespondsToSelector:@selector(downloadOperation:didFinishDownload:)]) {
???????????
dispatch_async(dispatch_get_main_queue(), ^{ // 回到主線程,傳遞圖片數(shù)據(jù)給代理對象
??????????????? [
self.delegatedownloadOperation:selfdidFinishDownload:image];
??????????? });
??????? }
??? }





總結(jié)

以上是生活随笔為你收集整理的iOS学习之多线程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。