整理一下自己這些時間學習的東西

1. gcd定時器

一個簡單的封裝

@interface CXGCDTimer : NSObject
+(instancetype)timerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)())block;`
/**
 暫停
 */
-(void)suspend;

/**
 清除定時器
 */
-(void)clear;
@end

#import "CXGCDTimer.h"

@interface CXGCDTimer ()

@property(nonatomic,copy)dispatch_block_t block;
@property(nonatomic, strong)dispatch_source_t timer;
@end

@implementation CXGCDTimer
+(instancetype)timerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)())block
{
    CXGCDTimer *gcdTimer = [[CXGCDTimer alloc]init];
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, interval * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(timer, block);
    dispatch_resume(timer);
    gcdTimer.timer = timer;
    
    return gcdTimer;
}

-(void)suspend
{
    dispatch_suspend(self.timer);
}

-(void)clear
{
    if (self.timer) {
        dispatch_source_cancel(self.timer);
        self.timer = nil;
    }
    self.block = nil;
}

2. gcd隊列

  • 和operation queue一樣都是基于隊列的并發API,他們通過集中管理大家協同使用的線程池
  • 公開的5個不同隊列:運行在主線程的main queue,3個不同優先級的后臺隊列(high priority queue,default priority queue,low priority queue),以及一個優先級更低的后臺隊列background priority queue(用于I/O)
  • 可創建自定義隊列:串行或者并行隊列。自定義一般放在default priority queue和main queue
  • 操作是在多線程上還是單線程主要是看隊列的類型和執行方法,并行隊列異步執行才能在多線程,并行隊列同步執行只會在這個并行隊列在隊列中被分配的那個線程執行。
基本概念
  • 系統的兩個標準隊列
    //全局隊列,一個并行隊列
    dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
    //主隊列,主線程中的唯一隊列,一個串行隊列,所有的UI都是在主線程中完成
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
  • 自定義隊列
    //串行隊列
    dispatch_queue_t serialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
    //并行隊列
    dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
  • 同步、異步線程創建
dispatch_sync(..., <#^(void)block#>)
dispatch_async(..., <#^(void)block#>)
隊列
  • Serial:又叫private dispatch queues,同時只能執行一個任務。Serial queue常用來同步訪問特定的資源或數據。當你創建多個serial queue時,雖然各自是同步的,但是serial queue之間是并發執行的.
  • Main dispatch queue:主隊列,全局可用的serial queue,在應用程序主線程上執行任務
  • concurrent:又叫global dispatch queue,可以并發執行多個任務,但是執行完成順序是隨機的。系統提供四個全局并發隊列,這四個隊列有著對應的優先級,用戶不能夠創建全局隊列,只能獲取。
    dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
  • user create queue:用戶自己定義的隊列,可以用dispatch_queue_create函數,函數有兩個參數,第一個是自定義的隊列名,第二個是隊列類型,默認為NULL或者DISPATCH_QUEUE_SERIAL的是串行,參數為DISPATCH_QUEUE_CONCURRENT是并行隊列。
dispatch_group_enter、dispatch_group_leave和dispatch_group_asyn.
 NSLog(@"任務開始");
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_enter(group);
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        sleep(5);
        NSLog(@"異步并行隊列1");
        dispatch_group_leave(group);
    });
    
    dispatch_group_enter(group);
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        sleep(10);
        NSLog(@"異步并行隊列2");
        dispatch_group_leave(group);
    });
    
    dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{
        NSLog(@"任務完成");
    });
NSLog(@"任務開始");
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
        sleep(5);
        NSLog(@"async異步并行隊列1");
    });
    dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
        sleep(8);
        NSLog(@"async異步并行隊列2");
    });
    
    dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{
        NSLog(@"任務完成");
    });

dispatch_group_enter和dispatch_group_leave需要成對出現。當enter和leave之間執行的任務是同步的時候,可以用dispatch_group_async代替,都會在任務執行完成后觸發dispatch_group_notify通知。
當enter和leave之間執行的任務是異步的時候,不能代替。

  1. 信號量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        sleep(2);
        NSLog(@"semaphore");
        dispatch_semaphore_signal(semaphore);
    });
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    NSLog(@"xxxxxx");

dispatch_semaphore_t可以達到鎖的目的

  1. 死鎖
    在串行隊列里同步調用此串行隊列的同步任務就會死鎖
NSLog(@"00000");
    dispatch_sync(dispatch_get_main_queue(), ^{
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"111111");
        });
    });
    NSLog(@"22222");

當前串行隊列里面同步執行當前串行隊列就會死鎖,解決的方法就是將同步的串行隊列放到另外一個線程就能夠解決。

細說GCD(Grand Central Dispatch)如何用

使用dispatch_group來進行線程同步

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容