iOS - Concurrency Programming Guide (iOS并行编程指南)


当代码中需要异步执行一些工作的时候,需要用到异步编程的技术。在iOS下进行并行编程的方法有四种:

1. Operation Queues:把要执行的工作打包成一个Objective-C对象,并且该对象的class类型必须继承自NSOperation。

2. Dispatch Queues:把要执行的工作打包成一个函数或一个block对象。有两种该类型的queue:serial dispatch queue,concurrent dispatch queue。区别在于:serial dispatch queue采取FIFO的原则,执行完一个task之后,再去从queue里取出另外一个task执行,也就是说第二个task开始执行时,第一个task肯定都执行完了。而concurrent dispatch queue虽然也是采取FIFO的原则,但后面的task不会等前面的task执行完后再执行,而是真的并行。

3. Dispatch Sources:异步的处理来自系统的事件。

4. 线程:用线程相关的函数创建一个新的线程,在新线程里完成需要异步进行的工作。这是最原始的方法,在iOS上不鼓励。


在平常的工作中,最常用的是 Dispatch Queues ,其他三种几乎不用。下面就重点介绍下 Dispatch Queues 。


Dispatch Queues的类型


类型

描述

Serial

又被称为private dispatch queues,会在一个不同的线程按照FIFO的顺序执行task。可通过dispatch_queue_create创建任意数量的

serial queue,注意的是各个queue之间是完全并行的,但每一个queue内的task是按照顺序一个一个执行的。

Concurrent

又被称为global dispatch queue,task依然会按照FIFO的顺序取出执行,但下一个task不会等待上一个task完成才去执行,task之间

是完全并行的。这些task实际上会被扔到多个不同的线程里并行执行。系统预置了4种global dispatch queue,这4种queue的区别在

于其优先级的不同。另外,因为这些预置的queue是global的,所以不用考虑retain、release的问题。

Main dispatch queue

是一个global的serial queue,只不过与main thread线程绑定了,可以在application的main thread里按照FIFO的顺序执行task。可

以通过dispatch_get_main_queue获取该queue。

相关API

1. dispatch_get_current_queue

这个接口一般用于debug或测试:在block内部调用该接口,可以得到该block被投递到哪个queue里了;在block外部调用该接口,可得到当前默认的concurrent queue。

2. dispatch_get_main_queue

得到当前与main thread绑定的 global Serial dispatch queue。

3. dispatch_get_global_queue

得到当前系统预置的 global Concurrent dispatch queue。

4. dispatch_queue_create

创建一个新的 Serial dispatch queue。


dispatch queue的内存管理

1. 对于自己创建的(private dispatch queue),需要通过 dispatch_retain  dispatch_release 管理queue对象的生存期。

2. 对于 global dispatch queue,系统会自动处理,不用程序员管了。


为queue绑定自定义数据(context data)

可以通过 dispatch_set_context and dispatch_get_context 为所有类型的queue绑定自定义的数据,称之为context,该context数据的 allocate 和 deallocate 由程序员负责。


Serial dispatch queue设置一个clean up的函数

创建一个Serial dispatch queue之后,可以为该queue设置一个clean up函数,该函数会在queue被 deallocate 之前调用,主要用于释放context data。如果没有为该queue绑定context data,也即context指针为NULL,那么该clean up函数将不会被调用。

示例: Installing a queue clean up function

void myFinalizerFunction(void *context)
{
    MyDataContext* theData = (MyDataContext*)context;
 
    // Clean up the contents of the structure
    myCleanUpDataContextFunction(theData);
 
    // Now release the structure itself.
    free(theData);
}
 
dispatch_queue_t createMyQueue()
{
    MyDataContext*  data = (MyDataContext*) malloc(sizeof(MyDataContext));
    myInitializeDataContextFunction(data);
 
    // Create the queue and set the context data.
    dispatch_queue_t serialQueue = dispatch_queue_create("com.example.CriticalTaskQueue", NULL);
    if (serialQueue)
    {
        dispatch_set_context(serialQueue, data);
        dispatch_set_finalizer_f(serialQueue, &myFinalizerFunction);
    }
 
    return serialQueue;
}


向Queue中添加task

有两种方式:同步(synchronously异步(asynchronously

同步API: dispatch_sync 和 dispatch_sync_f

异步API:dispatch_async 和 dispatch_async_f

在实际中,使用同步的方式很少,比如为了避免race condition等。

示例:dispatching tasks asynchronously and synchronously:

dispatch_queue_t myCustomQueue;
myCustomQueue = dispatch_queue_create("com.example.MyCustomQueue", NULL);
 
dispatch_async(myCustomQueue, ^{
    printf("Do some work here.\n");
});
 
printf("The first block may or may not have run.\n");
 
dispatch_sync(myCustomQueue, ^{
    printf("Do some more work here.\n");
});
printf("Both blocks have completed.\n");


Performing a Completion Block When a Task Is Done

有时候我们希望知道被异步执行的task在什么时候完成,并且能将执行结果返回给我们,这时候就可以在task的末尾再一次通过 dispatch_async 将另一个block dispatch到指定的queue,并将task执行的结果返回给该queue。

示例:Executing a completion callback after a task

void average_async(int *data, size_t len,
   dispatch_queue_t queue, void (^block)(int))
{
   // Retain the queue provided by the user to make
   // sure it does not disappear before the completion
   // block can be called.
   dispatch_retain(queue);
 
   // Do the work on the default concurrent queue and then
   // call the user-provided block with the results.
   dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
      int avg = average(data, len);
      dispatch_async(queue, ^{ block(avg);});
 
      // Release the user-provided queue when done
      dispatch_release(queue);
   });
}


Suspending and Resuming Queues

dispatch_suspend让queue暂停执行blocks,并且将 suspension reference count 加 一

dispatch_resume:恢复执行blocks,并且将 suspension reference count 减 一

只要 suspension reference count 的值大于0,那该queue就是 suspended 状态,因此要平衡好 dispatch_suspend 和 dispatch_resume 的调用次数。


Waiting on Groups of Queued Tasks

如果要阻塞一个线程,以便等待一个或多个task完成,就可以采用 Dispatch groups 技术。相关API为:dispatch_group_async 和 dispatch_group_wait

示例:Waiting on asynchronous tasks

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
 
// Add a task to the group
dispatch_group_async(group, queue, ^{
   // Some asynchronous work
});
 
// Do some other work while the tasks execute.
 
// When you cannot make any more forward progress,
// wait on the group to block the current thread.
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
 
// Release the group when it is no longer needed.
dispatch_release(group);


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Mastering macOS Programming by Stuart Grimshaw English | 31 May 2017 | ASIN: B01LWACIKS | 626 Pages | AZW3 | 6.43 MB Key Features Learn to harness the power of macOS with the elegance of the Swift programming language Become highly competent in building apps on the macOS platform Get the most in-depth guide with a hands-on approach on the latest version of macOS Book Description macOS continues to lead the way in desktop operating systems, with its tight integration across the Apple ecosystem of platforms and devices. With this book, you will get an in-depth knowledge of working on macOS, enabling you to unleash the full potential of the latest version using Swift 3 to build applications. This book will help you broaden your horizons by taking your programming skills to next level. The initial chapters will show you all about the environment that surrounds a developer at the start of a project. It introduces you to the new features that Swift 3 and Xcode 8 offers and also covers the common design patterns that you need to know for planning anything more than trivial projects. You will then learn the advanced Swift programming concepts, including memory management, generics, protocol orientated and functional programming and with this knowledge you will be able to tackle the next several chapters that deal with Apple's own Cocoa frameworks. It also covers AppKit, Foundation, and Core Data in detail which is a part of the Cocoa umbrella framework. The rest of the book will cover the challenges posed by asynchronous programming, error handling, debugging, and many other areas that are an indispensable part of producing software in a professional environment. By the end of this book, you will be well acquainted with Swift, Cocoa, and AppKit, as well as a plethora of other essential tools, and you will be ready to tackle much more complex and advanced software projects. What You Will Learn Combine beautiful design with robust code for the very best user experienc
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值