使用 Dispatch Queues 实现 Job Scheduler

Implement a Job Scheduler using Dispatch Queues

问题:实现一个作业调度程序,它接受函数 f 和 int n,并在 n 秒后调用 f。

既然我使用 Obj C 来回答这个问题,我可能应该使用调度队列而不是选择器或函数指针。

这是我实现答案的尝试,但它没有返回时间戳:

void jobSch(dispatch_queue_t queue, int64_t n, dispatch_block_t f)
{
    NSLog(@"%d\n", n);
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, n * NSEC_PER_SEC), dispatch_get_main_queue(), f);
}

void (^aBlock)(void) = ^(){
    NSDateFormatter *dateFormatter=[[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSLog(@"%@",[dateFormatter stringFromDate:[NSDate date]]);
};

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_group_t group = dispatch_group_create();
        dispatch_group_async(group, queue, ^{
            jobSch(queue, 3, aBlock);
        });
        dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    }
    return 0;
}

我可能做错了什么?

此外,我的预期实现将能够在运行时 0 调用 jobSch(queue, 10, aBlock) 并在运行时 2 调用 jobSch(queue, 3, aBlock),因此这意味着第二次调用将在第一次调用之前打印.

问题是 main 在您的排队块 运行 之前很久就退出了。那是因为您对 dispatch_group_wait 的呼叫没有等待。那是因为你的调度组是空的。

为了使调度组和对 dispatch_group_wait 的调用有用,您需要对 dispatch_group_enterdispatch_group_leave.

进行配对调用

您需要在开始任何异步调用之前调用 dispatch_group_enter,并且您需要在块完成后调用 dispatch_group_leave(在本例中为 aBlock)。

您的代码未设置为简化此操作。您需要将 group 设为全局变量。然后你可以在需要的地方调用 dispatch_group_enterdispatch_group_leave

像这样的东西应该可以工作:

dispatch_group_t group;

void jobSch(dispatch_queue_t queue, int64_t n, dispatch_block_t f)
{
    NSLog(@"%d\n", n);
    dispatch_group_enter(group);
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, n * NSEC_PER_SEC), queue, f);
}

void (^aBlock)(void) = ^(){
    NSDateFormatter *dateFormatter=[[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSLog(@"%@",[dateFormatter stringFromDate:[NSDate date]]);
    dispatch_group_leave(group);
};

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        group = dispatch_group_create();

        // no need for dispatch_group_async here
        jobSch(queue, 10, aBlock);
        jobSch(queue, 3, aBlock);

        dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    }
    return 0;
}

另请注意,您实际上从未在 jobSch 中使用 queue

您需要更改:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, n * NSEC_PER_SEC), dispatch_get_main_queue(), f);

至:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, n * NSEC_PER_SEC), queue, f);