Replacing Threads with Dispatch Queues

To understand how you might replace threads with dispatch queues, first consider some of the ways you might be using threads in your application today:

  • Single task threads. Create a thread to perform a single task and release the thread when the task is done.

  • Worker threads. Create one or more worker threads with specific tasks in mind for each. Dispatch tasks to each thread periodically.

  • Thread pools. Create a pool of generic threads and set up run loops for each one. When you have a task to perform, grab a thread from the pool and dispatch the task to it. If there are no free threads, queue the task and wait for a thread to become available.

Although these might seem like dramatically different techniques, they are really just variants on the same principle. In each case, a thread is being used to run some task that the application has to perform. The only difference between them is the code used to manage the threads and the queueing of tasks. With dispatch queues and operation queues, you can eliminate all of your thread and thread-communication code and instead focus on just the tasks you want to perform.

If you are using one of the above threading models, you should already have a pretty good idea of the type of tasks your application performs. Instead of submitting a task to one of your custom threads, try encapsulating that task in an operation object or a block object and dispatching it to the appropriate queue. For tasks that are not particularly contentious—that is, tasks that do not take locks—you should be able to make the following direct replacements:

  • For a single task thread, encapsulate the task in a block or operation object and submit it to a concurrent queue.

  • For worker threads, you need to decide whether to use a serial queue or a concurrent queue. If you use worker threads to synchronize the execution of specific sets of tasks, use a serial queue. If you do use worker threads to execute arbitrary tasks with no interdependencies, use a concurrent queue.

  • For thread pools, encapsulate your tasks in a block or operation object and dispatch them to a concurrent queue for execution.

Of course, simple replacements like this may not work in all cases. If the tasks you are executing contend for shared resources, the ideal solution is to try to remove or minimize that contention first. If there are ways that you can refactor or rearchitect your code to eliminate mutual dependencies on shared resources, that is certainly preferable. However, if doing so is not possible or might be less efficient, there are still ways to take advantage of queues. A big advantage of queues is that they offer a more predictable way to execute your code. This predictability means that there are still ways to synchronize the execution of your code without using locks or other heavyweight synchronization mechanisms. Instead of using locks, you can use queues to perform many of the same tasks:

  • If you have tasks that must execute in a specific order, submit them to a serial dispatch queue. If you prefer to use operation queues, use operation object dependencies to ensure that those objects execute in a specific order.

  • If you are currently using locks to protect a shared resource, create a serial queue to execute any tasks that modify that resource. The serial queue then replaces your existing locks as the synchronization mechanism. For more information techniques for getting rid of locks, see Eliminating Lock-Based Code.

  • If you use thread joins to wait for background tasks to complete, consider using dispatch groups instead. You can also use an  NSBlockOperation object or operation object dependencies to achieve similar group-completion behaviors. For more information on how to track groups of executing tasks, see Replacing Thread Joins.

  • If you use a producer-consumer algorithm to manage a pool of finite resources, consider changing your implementation to the one shown in Changing Producer-Consumer Implementations.

  • If you are using threads to read and write from descriptors, or monitor file operations, use the dispatch sources as described in Dispatch Sources.

It is important to remember that queues are not a panacea for replacing threads. The asynchronous programming model offered by queues is appropriate in situations where latency is not an issue. Even though queues offer ways to configure the execution priority of tasks in the queue, higher execution priorities do not guarantee the execution of tasks at specific times. Therefore, threads are still a more appropriate choice in cases where you need minimal latency, such as in audio and video playback.

https://developer.apple.com/library/content/documentation/General/Conceptual/ConcurrencyProgrammingGuide/ThreadMigration/ThreadMigration.html#//apple_ref/doc/uid/TP40008091-CH105-SW10

最新文章

  1. 用python实现逻辑回归
  2. ubuntu安装使用latex和texmaker--PC端
  3. linux网站服务Apache+php+mysql的安装
  4. 纪念逝去的岁月——C++实现一个队列(使用类模板)
  5. linux初始化配置---主机名、关闭防火墙、关闭selinux
  6. Mecanim的Retargeting和BodyMask
  7. hdu 2091
  8. C语言函数返回数组
  9. 1_jz2440在linux下烧写裸机程序
  10. javascript 中 keyup、keypress和keydown事件
  11. Maven 结合 IDEA 入门实践
  12. idea 配置git
  13. 如何在 Koa 中获取 client 的 ip 以及 port
  14. ABP 设置默认为中文
  15. 【XSY1642】Another Boring Problem 树上莫队
  16. 『Python CoolBook』Cython
  17. .net core通过发布nuget实现引用项目
  18. underscore.js源码解析【函数】
  19. MySQL主从复制配置遇到的部分问题
  20. 【转】用emWin进度条控件做个表盘控件,效果不错

热门文章

  1. memory management in oracle 11G R2
  2. Oops, 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine error
  3. 【转】gcov lcov 覆盖c/c++项目入门
  4. 再次讨论javascript 中的this
  5. oracle em 5500访问问题
  6. iOS中xib与storyboard原理,与Android界面布局的异同
  7. poj 1190 生日蛋糕 , 强剪枝
  8. MongoDB使用初步
  9. BestCoder Round #60.1003.GT and set/HDU5506 dfs
  10. IJ:IJ笔记1