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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

多线程实现的几种方式

發布時間:2024/3/26 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多线程实现的几种方式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

多線程實現一共有四種方式,如下圖:

- pthread的使用

  - 定義pthread

typedef __darwin_pthread_t pthread_t;

  - 創建pthread

int pthread_create(pthread_t * __restrict, const pthread_attr_t * __restrict,void *(*)(void *), void * __restrict);

  - 范例

void * run(void *param) {for (NSInteger i = 0; i<50000; i++) {NSLog(@"------buttonClick---%zd--%@", i, [NSThread currentThread]);}return NULL; }- (IBAction)buttonClick:(id)sender {pthread_t thread;pthread_create(&thread, NULL, run, NULL);pthread_t thread2;pthread_create(&thread2, NULL, run, NULL); }

-?NSThread

  -?創建和啟動線程

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

  - 主線程相關用法

+ (NSThread *)mainThread; // 獲得主線程 - (BOOL)isMainThread; // 是否為主線程 + (BOOL)isMainThread; // 是否為主線程

  - 獲取當前線程

NSThread *current = [NSThread currentThread];

  - 線程的名字

- (void)setName:(NSString *)n; - (NSString *)name;

  - 其它方式創建線程

    -?創建線程后自動啟動線程

[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];

    -?隱式創建并啟動線程

[self performSelectorInBackground:@selector(run) withObject:nil];

    

    -?上述2種創建線程方式的優缺點

      -?優點:簡單快捷

      -?缺點:無法對線程進行更詳細的設置

    

    - 線程的狀態

      

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

    -?阻塞(暫停)線程

+ (void)sleepUntilDate:(NSDate *)date; + (void)sleepForTimeInterval:(NSTimeInterval)ti; // 進入阻塞狀態

    - 強制停止線程

+ (void)exit; // 進入死亡狀態

注意:一旦線程停止(死亡)了,就不能再次開啟任務

??   - 多線程的隱患

      -?資源共享

        -?1塊資源可能會被多個線程共享,也就是多個線程可能會訪問同一塊資源

        -?比如多個線程訪問同一個對象、同一個變量、同一個文件

?      -?當多個線程訪問同一塊資源時,很容易引發數據錯亂和數據安全問題

     

    - 解決方法:互斥鎖

  

    -?互斥鎖使用格式

@synchronized(鎖對象) { // 需要鎖定的代碼 }

注意:鎖定1份代碼只用1把鎖,用多把鎖是無效的

    -?互斥鎖的優缺點

      - 優點:能有效防止因多線程搶奪資源造成的數據安全問題

      -?缺點:需要消耗大量的CPU資源

    -?互斥鎖的使用前提:多條線程搶奪同一塊資源

    -?相關專業術語:線程同步

      -?線程同步的意思是:多條線程在同一條線上執行(按順序地執行任務)

      -?互斥鎖,就是使用了線程同步技術

  - 原子和非原子屬性

    -?OC在定義屬性時有nonatomic和atomic兩種選擇

       -?atomic:原子屬性,為setter方法加鎖(默認就是atomic)

       -?nonatomic:非原子屬性,不會為setter方法加鎖

  -?nonatomic和atomic對比

    -?atomic:線程安全,需要消耗大量的資源

    -?nonatomic:非線程安全,適合內存小的移動設備

  -?iOS開發的建議

    -?所有屬性都聲明為nonatomic

    -?盡量避免多線程搶奪同一塊資源

    -?盡量將加鎖、資源搶奪的業務邏輯交給服務器端處理,減小移動客戶端的壓力

  

-?GCD的使用

  -?什么是GCD

    -?全稱是Grand Central Dispatch,可譯為“牛逼的中樞調度器”

    -?純C語言,提供了非常多強大的函數

  -?GCD的優勢

  -?GCD是蘋果公司為多核的并行運算提出的解決方案

  -?GCD會自動利用更多的CPU內核(比如雙核、四核)

  -?GCD會自動管理線程的生命周期(創建線程、調度任務、銷毀線程)

  -?程序員只需要告訴GCD想要執行什么任務,不需要編寫任何線程管理代碼

  -?GCD中有2個核心概念

    -?任務:執行什么操作

    -?隊列:用來存放任務

  -?GCD的使用就2個步驟

    -?定制任務

    -?確定想做的事情

?  

  -?將任務添加到隊列中

    -?GCD會自動將隊列中的任務取出,放到對應的線程中執行

    -?任務的取出遵循隊列的FIFO原則:先進先出,后進后出

  -?GCD中有2個用來執行任務的常用函數

    -?用同步的方式執行任務

// queue:隊列 block:任務 dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);

  -?用異步的方式執行任務

dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

  -?同步和異步的區別

    -?同步:只能在當前線程中執行任務,不具備開啟新線程的能力

    -?異步:可以在新的線程中執行任務,具備開啟新線程的能力

  -?GCD中還有個用來執行任務的函數,在前面的任務執行結束后它才執行,而且它后面的任務等它執行完成之后才會執行:

// 這個queue不能是全局的并發隊列 dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);  

  -?隊列的類型

    -?GCD的隊列可以分為2大類型

      -?并發隊列(Concurrent Dispatch Queue)

        -?可以讓多個任務并發(同時)執行(自動開啟多個線程同時執行任務)

        -?并發功能只有在異步(dispatch_async)函數下才有效

      -?串行隊列(Serial Dispatch Queue)

        -?讓任務一個接著一個地執行(一個任務執行完畢后,再執行下一個任務)

  -?并發隊列
    - 自己創建的
    - 全局
  -?串行隊列
    - 主隊列
    - 自己創建的

  -?同步和異步主要影響:能不能開啟新的線程

    -?同步:只是在當前線程中執行任務,不具備開啟新線程的能力

    -?異步:可以在新的線程中執行任務,具備開啟新線程的能力

  -?并發和串行主要影響:任務的執行方式

    -?并發:允許多個任務并發(同時)執行

    -?串行:一個任務執行完畢后,再執行下一個任務

?    

  -?并發隊列

// 使用dispatch_queue_create函數創建隊列 dispatch_queue_t dispatch_queue_create(const char *label, // 隊列名稱 dispatch_queue_attr_t attr); // 隊列的類型// 創建并發隊列 dispatch_queue_t queue = dispatch_queue_create("com.samyang.queue", DISPATCH_QUEUE_CONCURRENT);

// GCD默認已經提供了全局的并發隊列,供整個應用使用,可以無需手動創建 使用dispatch_get_global_queue函數獲得全局的并發隊列 dispatch_queue_t dispatch_get_global_queue( dispatch_queue_priority_t priority, // 隊列的優先級 unsigned long flags); // 此參數暫時無用,用0即可// 獲得全局并發隊列 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 全局并發隊列的優先級 #define DISPATCH_QUEUE_PRIORITY_HIGH 2 // 高 #define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默認(中) #define DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低 #define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后臺

  -?串行隊列

// GCD中獲得串行有2種途徑 // 使用dispatch_queue_create函數創建串行隊列 // 創建串行隊列(隊列類型傳遞NULL或者DISPATCH_QUEUE_SERIAL) dispatch_queue_t queue = dispatch_queue_create("com.samyang.queue", NULL); /*使用主隊列(跟主線程相關聯的隊列) 主隊列是GCD自帶的一種特殊的串行隊列 放在主隊列中的任務,都會放到主線程中執行 使用dispatch_get_main_queue()獲得主隊列*/ dispatch_queue_t queue = dispatch_get_main_queue();

  -?各種隊列的執行效果

-?注意:使用sync函數往當前串行隊列中添加任務,會卡住當前的串行隊列

  - 延時執行

    -?iOS常見的延時執行

// 調用NSObject的方法 [self performSelector:@selector(run) withObject:nil afterDelay:2.0]; // 2秒后再調用self的run方法// 使用GCD函數 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{// 2秒后執行這里的代碼... });// 使用NSTimer [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(test) userInfo:nil repeats:NO];

  - 一次性代碼(比如說單例模式singleton)

// 使用dispatch_once函數能保證某段代碼在程序運行過程中只被執行1次 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{// 只執行1次的代碼(這里面默認是線程安全的) });

  - 快速迭代

// 使用dispatch_apply函數能進行快速迭代遍歷 dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index){// 執行10次代碼,index順序不確定 });

  - 隊列組

    -有這么1種需求

      -?首先:分別異步執行2個耗時的操作

      -?其次:等2個異步操作都執行完畢后,再回到主線程執行操作

// 如果想要快速高效地實現上述需求,可以考慮用隊列組 dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{// 執行1個耗時的異步操作 }); dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{// 執行1個耗時的異步操作 }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{// 等前面的異步操作都執行完畢后,回到主線程... });

-?NSOperation

NSOperationQueue的隊列類型

  • 主隊列
    • [NSOperationQueue mainQueue]
    • 凡是添加到主隊列中的任務(NSOperation),都會放到主線程中執行
  • 非主隊列(其他隊列)
    • [[NSOperationQueue alloc] init]
    • 同時包含了:串行、并發功能
    • 添加到這種隊列中的任務(NSOperation),就會自動放到子線程中執行

NSOperation的作用

  • 配合使用NSOperation和NSOperationQueue也能實現多線程編程

  • NSOperation和NSOperationQueue實現多線程的具體步驟

    • 先將需要執行的操作封裝到一個NSOperation對象中
    • 然后將NSOperation對象添加到NSOperationQueue中
    • 系統會自動將NSOperationQueue中的NSOperation取出來
    • 將取出的NSOperation封裝的操作放到一條新線程中執行

NSOperation的子類

  • NSOperation是個抽象類,并不具備封裝操作的能力,必須使用它的子類

  • 使用NSOperation子類的方式有3種

    • NSInvocationOperation
    • NSBlockOperation
    • 自定義子類繼承NSOperation,實現內部相應的方法

NSInvocationOperation

  • 創建NSInvocationOperation對象
- (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;

  • 調用start方法開始執行操作
- (void)start;

  • 一旦執行操作,就會調用target的sel方法

  • 注意

    • 默認情況下,調用了start方法后并不會開一條新線程去執行操作,而是在當前線程同步執行操作
    • 只有將NSOperation放到一個NSOperationQueue中,才會異步執行操作
  • NSBlockOperation

    • 創建NSBlockOperation對象
+ (id)blockOperationWithBlock:(void (^)(void))block;

    - 通過addExecutionBlock:方法添加更多的操作 - (void)addExecutionBlock:(void (^)(void))block;

  • 注意:只要NSBlockOperation封裝的操作數 > 1,就會異步執行

  -?NSOperationQueue

    -?NSOperationQueue的作用

      - NSOperation可以調用start方法來執行任務,但默認是同步執行的

      -?如果將NSOperation添加到NSOperationQueue(操作隊列)中,系統會自動異步執行NSOperation中的操作

    -?添加操作到NSOperationQueue中

- (void)addOperation:(NSOperation *)op;- (void)addOperationWithBlock:(void (^)(void))block;

  - 最大并發數

    -?什么是并發數

        -?同時執行的任務數

        -?比如,同時開3個線程執行3個任務,并發數就是3

     -?最大并發數的相關方法

- (NSInteger)maxConcurrentOperationCount;- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;

 

   -?隊列的取消、暫停、恢復

?取消隊列的所有操作

- (void)cancelAllOperations;

-?提示:也可以調用NSOperation的- (void)cancel方法取消單個操作

  ?-?暫停和恢復隊列

- (void)setSuspended:(BOOL)b; // YES代表暫停隊列,NO代表恢復隊列- (BOOL)isSuspended;

  -?操作優先級

 設置NSOperation在queue中的優先級,可以改變操作的執行優先級

- (NSOperationQueuePriority)queuePriority;- (void)setQueuePriority:(NSOperationQueuePriority)p;

  -?優先級的取值

NSOperationQueuePriorityVeryLow = -8L, NSOperationQueuePriorityLow = -4L, NSOperationQueuePriorityNormal = 0, NSOperationQueuePriorityHigh = 4, NSOperationQueuePriorityVeryHigh = 8

  -?操作依賴

    -?NSOperation之間可以設置依賴來保證執行順序

    - 比如一定要讓操作A執行完后,才能執行操作B,可以這么寫

[operationB addDependency:operationA]; // 操作B依賴于操作A

  -?可以在不同queue的NSOperation之間創建依賴關系

 注意:不能相互依賴,比如A依賴B,B依賴A  

  -?操作的監聽

 

      -?可以監聽一個操作的執行完畢

- (void (^)(void))completionBlock;- (void)setCompletionBlock:(void (^)(void))block;

  

  -?自定義NSOperation

     -?自定義NSOperation的步驟很簡單

        -?重寫- (void)main方法,在里面實現想執行的任務

     -?重寫- (void)main方法的注意點

        -?自己創建自動釋放池(因為如果是異步操作,無法訪問主線程的自動釋放池)

        -?經常通過- (BOOL)isCancelled方法檢測操作是否被取消,對取消做出響應

多線程實現的幾種方式 - samyang1107 - 博客園 (cnblogs.com)

總結

以上是生活随笔為你收集整理的多线程实现的几种方式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。