多線程GCD

多線程GCD

標籤(空格分隔): 網絡多線程


GCD

GCD是蘋果公司爲多核的並行運算提出的解決方案,全稱是Grand Central Dispatch,是牛逼的中樞調度器,GCD提供了非常多強大的函數,GCD會自動利用更多的CPU內核,會自動管理線程的生命週期。

GCD的使用步驟

  • 定製任務:要做得事情
  • 將任務添加到隊列中
    • GCD會自動將隊列中的任務取出,放到對應的線程中執行
    • 任務的取出遵循隊列的FIFO原則:先進先出,後進後出

執行任務

  • 同步方式執行任務:只能在當前線程中執行任務,不具備開啓新線程的能力
`dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);`
queue:隊列
block:任務
  • 用異步的方式執行任務:可以在新的線程中執行任務,具備開啓新線程的能力
`dispatch_async(dispatch_queue_t queue, dispatch_block_t block);`
  • 其它
`dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);`

在前面的任務執行結束後它才執行,而且它後面的任務等它執行完成之後纔會執行,這個queue不能是全局的併發隊列

隊列類型

  • 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("pjl.queue", DISPATCH_QUEUE_CONCURRENT);
  • GCD默認已經提供了全局的併發隊列,供整個應用使用,可以無需手動創建
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); 

串行隊列

  • 使用dispatch_queue_create函數創建串行隊列
dispatch_queue_t queue = dispatch_queue_create("com.520it.queue", DISPATCH_QUEUE_SERIAL); //後面一個參數也可以寫NULL
  • 使用主隊列(主隊列是GCD自帶的一種特殊的串行隊列,但是放在主隊列的任務會放在主線程中執行)
    dispatch_queue_t queue = dispatch_get_main_queue();
    -各種隊列的執行效果

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

線程間通信

dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 執行耗時的異步操作...
      dispatch_async(dispatch_get_main_queue(), ^{
        // 回到主線程,執行UI刷新操作
        });
});

延時執行

- 調用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];

一次性代碼

  • 使用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(), ^{
    // 等前面的異步操作都執行完畢後,回到主線程...
});

單粒模式

  • 可以保證在程序運行過程,一個類只有一個實例,而且該實例易於供外界訪問,從而方便地控制了實例個數,並節約系統資源

ARC中,單例模式的實現

  • 在.m中保留一個全局的static的實例
    static id _instance;

  • 重寫allocWithZone:方法,在這裏創建唯一的實例(注意線程安全)

+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });
    return _instance;
}
  • 提供1個類方法讓外界訪問唯一的實例
+ (instancetype)sharedInstance
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc] init];
    });
    return _instance;
}
  • 實現copyWithZone:方法
- (id)copyWithZone:(struct _NSZone *)zone
{
    return _instance;
}

單粒宏定義

#define interfaceSingle(name)  + (instancetype)share##name

#if __has_feature(objc_arc)
// 如果是ARC
#define implementationSingle(name)  + (instancetype)share##name \
{ \
    return [[self alloc] init]; \
} \
static id _instance; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
    static dispatch_once_t onceToken; \
    dispatch_once(&onceToken, ^{ \
        _instance = [super allocWithZone:zone]; \
    }); \
    return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone \
{ \
    return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
    return _instance; \
}
#else
// 如果不是ARC
#define implementationSingle(name)  + (instancetype)share##name \
{ \
return [[self alloc] init]; \
} \
static id _instance; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [super allocWithZone:zone]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone \
{ \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return _instance; \
}\
- (oneway void)release \
{} \
- (instancetype)retain \
{ \
    return _instance; \
} \
- (NSUInteger)retainCount \
{ \
    return MAXFLOAT; \
}
#endif
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章