iOS 多线程 之 GCD(大中枢派发)(二)

本文接着上一篇讲。主要讲:dispatch_source。

dispatch_source主要用户监听事件,可以监听如下事件

DISPATCH_SOURCE_TYPE_DATA_ADD
DISPATCH_SOURCE_TYPE_DATA_OR
DISPATCH_SOURCE_TYPE_MACH_RECV
DISPATCH_SOURCE_TYPE_MACH_SEND
DISPATCH_SOURCE_TYPE_PROC
DISPATCH_SOURCE_TYPE_READ
DISPATCH_SOURCE_TYPE_SIGNAL
DISPATCH_SOURCE_TYPE_TIMER
DISPATCH_SOURCE_TYPE_VNODE
DISPATCH_SOURCE_TYPE_WRITE
DISPATCH_SOURCE_TYPE_MEMORYPRESSURE

比较常用的就是实现Timer与自定义事件(DISPATCH_SOURCE_TYPE_DATA_ADD、DISPATCH_SOURCE_TYPE_DATA_OR)。

一、实现timer

使用NSTimer会有循环引用的问题,使用dispatch_source就不会有问题,代码如下

__block NSInteger count = 0;
    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, 2.f * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(timer, ^{
        NSLog(@"count == %li", count++);
    });
    dispatch_resume(timer);

需要注意的是dispatch_source_t不会创建之后自动执行,需要显示的调用dispatch_resume才会执行,而且调用resume之后会立刻执行一次。

二、监听用户自定义事件

DISPATCH_SOURCE_TYPE_DATA_ADD会对用dispatch_source_merge_data提交的数据进行累加,DISPATCH_SOURCE_TYPE_DATA_OR则是对提交的数据进行或运算。示例代码如下

@interface ViewController10 ()

@property (nonatomic, strong) dispatch_source_t source;

@end

@implementation ViewController10

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"dispatch_source_t 实现自定义事件");
    //模拟器第一次执行会有卡顿,真机不会,俺也不知道原因
    __block NSInteger total = 0;
    dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_queue_create("com.wk.serialQueue", DISPATCH_QUEUE_CONCURRENT));
    dispatch_source_set_event_handler(source, ^{
        NSInteger result = dispatch_source_get_data(source);
        total += result;
        NSLog(@"total = %li", total);
    });
    
    dispatch_source_set_cancel_handler(source, ^{
        NSLog(@"取消了派发源");
    });
    
    dispatch_resume(source);
    
    self.source = source;
    
    dispatch_queue_t global = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0);
    
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);
    
    
    for (int i = 0; i < 100; i++) {
        dispatch_async(global, ^{
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            
            dispatch_source_merge_data(source, 1);
            
            sleep(1.f);
            
            dispatch_semaphore_signal(semaphore);
        });
    }
}

- (void)dealloc
{
    dispatch_source_cancel(self.source);
}
dispatch_source_cancel可以取消派发源,使派发员不在监听指定事件
你可以在这里下载demo

转载于:https://www.cnblogs.com/pretty-guy/p/8241178.html

猜你喜欢

转载自blog.csdn.net/weixin_34217773/article/details/93199971