美文网首页
iOS 多线程实现小结

iOS 多线程实现小结

作者: adduct | 来源:发表于2017-03-23 00:32 被阅读0次

简介

在iOS中,我们需要将非UI且耗时的任务放在主线程当中执行,同时确保在任务完成时进行回调。常用的三种实现多线程方式如下:

1. GCD

2. NSThread

3. NSOperation / NSOperationQueue

先就GCD小结下。

小结分析

下面分别予以简单小结。

一 GCD

GCD 是Grand Central Dispatch的缩写,是苹果提供的基于block回调的多线程实现方式。

GCD维护线程的创建和调度及生命周期,程序员只需负责进行业务逻辑的处理。

GCD有异步和同步执行任务两种处理方式.使用时,无须关心队列和任务的调度,由系统负责安排。相应的API函数定义在dispatch/queue.h当中。

根据该文档中的注释:

Dispatch is an abstract model for expressing concurrency via simple but

powerful API.

*

* At the core, dispatch provides serial FIFO queues to which blocks may be

* submitted. Blocks submitted to these dispatch queues are invoked on a pool

* of threads fully managed by the system. No guarantee is made regarding

* which thread a block will be invoked on; however, it is guaranteed that only

* one block submitted to the FIFO dispatch queue will be invoked at a time.

*

* When multiple queues have blocks to be processed, the system is free to

* allocate additional threads to invoke the blocks concurrently. When the

* queues become empty, these threads are automatically released.

/*!

* @typedef dispatch_queue_t

*

* @abstract

* Dispatch queues invoke blocks submitted to them serially in FIFO order. A

* queue will only invoke one block at a time, but independent queues may each

* invoke their blocks concurrently with respect to each other.

*

* @discussion

* Dispatch queues are lightweight objects to which blocks may be submitted.

* The system manages a pool of threads which process dispatch queues and

* invoke blocks submitted to them.

*

* Conceptually a dispatch queue may have its own thread of execution, and

* interaction between queues is highly asynchronous.

*

* Dispatch queues are reference counted via calls to dispatch_retain() and

* dispatch_release(). Pending blocks submitted to a queue also hold a

* reference to the queue until they have finished. Once all references to a

* queue have been released, the queue will be deallocated by the system.

*/

系统维护一个FIFO(先进先出顺序)的队列,提交到队列中的block任务由系统负责分配线程执行,但不能保证哪个线程会执行,且多个线程中只有一个保证在执行。当系统中线程数不够时,将自动创建线程。block为空时,对应的线程会自动被销毁。

dispatch通过dispatch_retain() 和dispatch_release()来进行引用记数管理。

(一)GCD的调用:

1.异步调用:

1.1 

void dispatch_async(dispatch_queue_tqueue,dispatch_block_tblock);

调用之后,会立即返回,不等待提交的block执行完成。

1.2

void dispatch_async_f(dispatch_queue_tqueue,

void*context,

dispatch_function_twork);

/*!

* @function dispatch_async_f

*

* @abstract

* Submits a function for asynchronous execution on a dispatch queue.

*

* @discussion

* See dispatch_async() for details.

*

* @param queue

* The target dispatch queue to which the function is submitted.

* The system will hold a reference on the target queue until the function

* has returned.

* The result of passing NULL in this parameter is undefined.

*

* @param context

* The application-defined context parameter to pass to the function.

*

* @param work

* The application-defined function to invoke on the target queue. The first

* parameter passed to this function is the context provided to

* dispatch_async_f().

* The result of passing NULL in this parameter is undefined.

*/

__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0)

DISPATCH_EXPORTDISPATCH_NONNULL1DISPATCH_NONNULL3DISPATCH_NOTHROW

void

dispatch_async_f(dispatch_queue_tqueue,

void*context,

dispatch_function_twork);

context可以传0或Nsnull,详见How to use dispatch_async_f

2. 同步调用:

2.1 void dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);

将block中的任务执行完成后才会返回。通常用于设置和与服务器同步,等待设置完成和服务器返回后才进行下一步操作。

/*!

* @function dispatch_sync

*

* @abstract

* Submits a block for synchronous execution on a dispatch queue.

*

* @discussion

* Submits a block to a dispatch queue like dispatch_async(), however

* dispatch_sync() will not return until the block has finished.

*

* Calls to dispatch_sync() targeting the current queue will result

* in dead-lock. Use of dispatch_sync() is also subject to the same

* multi-party dead-lock problems that may result from the use of a mutex.

* Use of dispatch_async() is preferred.

*

* Unlike dispatch_async(), no retain is performed on the target queue. Because

* calls to this function are synchronous, the dispatch_sync() "borrows" the

* reference of the caller.

*

* As an optimization, dispatch_sync() invokes the block on the current

* thread when possible.

*

* @param queue

* The target dispatch queue to which the block is submitted.

* The result of passing NULL in this parameter is undefined.

*

* @param block

* The block to be invoked on the target dispatch queue.

* The result of passing NULL in this parameter is undefined.

*/

#ifdef __BLOCKS__

__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0)

DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW

void

dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);

#endif

2.2 void dispatch_sync_f(dispatch_queue_t queue,

void *context,

dispatch_function_t work);

/*!

* @function dispatch_sync_f

*

* @abstract

* Submits a function for synchronous execution on a dispatch queue.

*

* @discussion

* See dispatch_sync() for details.

*

* @param queue

* The target dispatch queue to which the function is submitted.

* The result of passing NULL in this parameter is undefined.

*

* @param context

* The application-defined context parameter to pass to the function.

*

* @param work

* The application-defined function to invoke on the target queue. The first

* parameter passed to this function is the context provided to

* dispatch_sync_f().

* The result of passing NULL in this parameter is undefined.

*/

__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0)

DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW

void

dispatch_sync_f(dispatch_queue_t queue,

void *context,

dispatch_function_t work);

3. 多次调用

3.1 void dispatch_apply(size_titerations,dispatch_queue_tqueue, void(^block)(size_t));

函数原型如下:

/*!

* @function dispatch_apply

*

* @abstract

* Submits a block to a dispatch queue for multiple invocations.

*

* @discussion

* Submits a block to a dispatch queue for multiple invocations. This function

* waits for the task block to complete before returning. If the target queue

* is concurrent, the block may be invoked concurrently, and it must therefore

* be reentrant safe.

*

* Each invocation of the block will be passed the current index of iteration.

*

* @param iterations

* The number of iterations to perform.

*

* @param queue

* The target dispatch queue to which the block is submitted.

* The result of passing NULL in this parameter is undefined.

*

* @param block

* The block to be invoked the specified number of iterations.

* The result of passing NULL in this parameter is undefined.

*/

#ifdef __BLOCKS__

__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0)

DISPATCH_EXPORTDISPATCH_NONNULL3DISPATCH_NOTHROW

void

dispatch_apply(size_titerations,dispatch_queue_tqueue,

void(^block)(size_t));

#endif

3.2 void dispatch_apply_f(size_titerations,dispatch_queue_tqueue,

void*context,

void(*work)(void*,size_t));

/*!

* @function dispatch_apply_f

*

* @abstract

* Submits a function to a dispatch queue for multiple invocations.

*

* @discussion

* See dispatch_apply() for details.

*

* @param iterations

* The number of iterations to perform.

*

* @param queue

* The target dispatch queue to which the function is submitted.

* The result of passing NULL in this parameter is undefined.

*

* @param context

* The application-defined context parameter to pass to the function.

*

* @param work

* The application-defined function to invoke on the target queue. The first

* parameter passed to this function is the context provided to

* dispatch_apply_f(). The second parameter passed to this function is the

* current index of iteration.

* The result of passing NULL in this parameter is undefined.

*/

__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0)

DISPATCH_EXPORTDISPATCH_NONNULL4DISPATCH_NOTHROW

void

dispatch_apply_f(size_titerations,dispatch_queue_tqueue,

void*context,

void(*work)(void*,size_t));

(二)GCD的队列

GCD中有3个队列:

2.1 主队列

dispatch_get_main_queue(void)

主队列一般进行UI线程操作,及与用户交互。因此,对于长时间的复杂逻辑处理任务,一般都将放到后台队列当中进行。为了操作流畅和用户体验,网络请求及数据库操作等任务,都不要在主队列当中进行。

/*!

* @function dispatch_get_main_queue

*

* @abstract

* Returns the default queue that is bound to the main thread.

*

* @discussion

* In order to invoke blocks submitted to the main queue, the application must

* call dispatch_main(), NSApplicationMain(), or use a CFRunLoop on the main

* thread.

*

* @result

* Returns the main queue. This queue is created automatically on behalf of

* the main thread before main() is called.

*/

DISPATCH_INLINE DISPATCH_ALWAYS_INLINE DISPATCH_CONST DISPATCH_NOTHROW

dispatch_queue_t

dispatch_get_main_queue(void)

{

return DISPATCH_GLOBAL_OBJECT(dispatch_queue_t, _dispatch_main_q);

}

2.2 串行队列

创建:

dispatch_queue_t dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);

/*!

* @function dispatch_queue_create

*

* @abstract

* Creates a new dispatch queue to which blocks may be submitted.

*

* @discussion

* Dispatch queues created with the DISPATCH_QUEUE_SERIAL or a NULL attribute

* invoke blocks serially in FIFO order.

*

* Dispatch queues created with the DISPATCH_QUEUE_CONCURRENT attribute may

* invoke blocks concurrently (similarly to the global concurrent queues, but

* potentially with more overhead), and support barrier blocks submitted with

* the dispatch barrier API, which e.g. enables the implementation of efficient

* reader-writer schemes.

*

* When a dispatch queue is no longer needed, it should be released with

* dispatch_release(). Note that any pending blocks submitted to a queue will

* hold a reference to that queue. Therefore a queue will not be deallocated

* until all pending blocks have finished.

*

* Passing the result of the dispatch_queue_attr_make_with_qos_class() function

* to the attr parameter of this function allows a quality of service class and

* relative priority to be specified for the newly created queue.

* The quality of service class so specified takes precedence over the quality

* of service class of the newly created dispatch queue's target queue (if any)

* as long that does not result in a lower QOS class and relative priority.

*

* When no quality of service class is specified, the target queue of a newly

* created dispatch queue is the default priority global concurrent queue.

*

* @param label

* A string label to attach to the queue.

* This parameter is optional and may be NULL.

*

* @param attr

* DISPATCH_QUEUE_SERIAL, DISPATCH_QUEUE_CONCURRENT, or the result of a call to

* the function dispatch_queue_attr_make_with_qos_class().

*

* @result

* The newly created dispatch queue.

*/

__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0)

DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT

DISPATCH_NOTHROW

dispatch_queue_t

dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);

获取指定label的队列:

const char *dispatch_queue_get_label(dispatch_queue_t queue);

/*!

* @function dispatch_queue_get_label

*

* @abstract

* Returns the label of the given queue, as specified when the queue was

* created, or the empty string if a NULL label was specified.

*

* Passing DISPATCH_CURRENT_QUEUE_LABEL will return the label of the current

* queue.

*

* @param queue

* The queue to query, or DISPATCH_CURRENT_QUEUE_LABEL.

*

* @result

* The label of the queue.

*/

__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0)

DISPATCH_EXPORT DISPATCH_PURE DISPATCH_WARN_RESULT DISPATCH_NOTHROW

const char *

dispatch_queue_get_label(dispatch_queue_t queue);

2.3 全局队列

dispatch_get_global_queue(long identifier, unsigned long flags);

identifier表示优先级:有四个值:

DISPATCH_QUEUE_PRIORITY_HIGH:        高优先级,一般是需要处理的紧急任务或UI线程

 DISPATCH_QUEUE_PRIORITY_DEFAULT:      默认优先级

DISPATCH_QUEUE_PRIORITY_LOW:          低优先级

 DISPATCH_QUEUE_PRIORITY_BACKGROUND:后台进程,比如网络或数据库请求

flags为保留值,一般设为0.

/*!

* @function dispatch_get_global_queue

*

* @abstract

* Returns a well-known global concurrent queue of a given quality of service

* class.

*

* @discussion

* The well-known global concurrent queues may not be modified. Calls to

* dispatch_suspend(), dispatch_resume(), dispatch_set_context(), etc., will

* have no effect when used with queues returned by this function.

*

* @param identifier

* A quality of service class defined in qos_class_t or a priority defined in

* dispatch_queue_priority_t.

*

* It is recommended to use quality of service class values to identify the

* well-known global concurrent queues:

*  - QOS_CLASS_USER_INTERACTIVE

*  - QOS_CLASS_USER_INITIATED

*  - QOS_CLASS_DEFAULT

*  - QOS_CLASS_UTILITY

*  - QOS_CLASS_BACKGROUND

*

* The global concurrent queues may still be identified by their priority,

* which map to the following QOS classes:

*  - DISPATCH_QUEUE_PRIORITY_HIGH:        QOS_CLASS_USER_INITIATED

*  - DISPATCH_QUEUE_PRIORITY_DEFAULT:      QOS_CLASS_DEFAULT

*  - DISPATCH_QUEUE_PRIORITY_LOW:          QOS_CLASS_UTILITY

*  - DISPATCH_QUEUE_PRIORITY_BACKGROUND:  QOS_CLASS_BACKGROUND

*

* @param flags

* Reserved for future use. Passing any value other than zero may result in

* a NULL return value.

*

* @result

* Returns the requested global queue or NULL if the requested global queue

* does not exist.

*/

__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0)

DISPATCH_EXPORT DISPATCH_CONST DISPATCH_WARN_RESULT DISPATCH_NOTHROW

dispatch_queue_t

dispatch_get_global_queue(long identifier, unsigned long flags);

另外,调试和打日志时,需要用到

dispatch_queue_t dispatch_get_current_queue(void);

函数得到当前队列。

线程延时执行:可以使用

void dispatch_after(dispatch_time_t when,

dispatch_queue_t queue,

dispatch_block_t block);

/*!

* @function dispatch_after

*

* @abstract

* Schedule a block for execution on a given queue at a specified time.

*

* @discussion

* Passing DISPATCH_TIME_NOW as the "when" parameter is supported, but not as

* optimal as calling dispatch_async() instead. Passing DISPATCH_TIME_FOREVER

* is undefined.

*

* @param when

* A temporal milestone returned by dispatch_time() or dispatch_walltime().

*

* @param queue

* A queue to which the given block will be submitted at the specified time.

* The result of passing NULL in this parameter is undefined.

*

* @param block

* The block of code to execute.

* The result of passing NULL in this parameter is undefined.

*/

#ifdef __BLOCKS__

__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0)

DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_NONNULL3 DISPATCH_NOTHROW

void

dispatch_after(dispatch_time_t when,

dispatch_queue_t queue,

dispatch_block_t block);

#endif


相关文章

  • iOS 多线程实现小结

    简介 在iOS中,我们需要将非UI且耗时的任务放在主线程当中执行,同时确保在任务完成时进行回调。常用的三种实现多线...

  • IOS多线程二 NSThread简约而不简单

    IOS多线程二NSThread简约而不简单 今天就来着手教大家在IOS中简单的实现多线程。IOS实现多线程的方式有...

  • iOS中的多线程

    iOS中的多线程 现存的iOS多线程解决方案 现在在iOS中要实现多线程有如下四种方法。 PthreadsNSTh...

  • iOS-多线程

    iOS开发中常用的几种多线程方案,简单做个小结,方便日后查阅。 NSThead GCD NSOperation &...

  • IOS NSThread线程处理 子线程的启动与结束

    IOS NSThread线程处理 子线程的启动与结束 iOS多线程开发-多线程实现方式 -(void)blockO...

  • 多线程

    多线程: iOS 多线程实现的种类分别是NSThread\NSOperationQueue\NSObject\GC...

  • iOS 多线程基础

    转自:iOS 多线程基础 - 简书 多线程同步和异步的区别?IOS中如何实现多线程的同步? 异步:可以同时执行多条...

  • iOS 多线程

    参考链接 iOS多线程iOS 多线程:『GCD』详尽总结iOS简单优雅的实现复杂情况下的串行需求(各种锁、GCD ...

  • 整理

    KVO的实现原理与具体应用 2.通知 3.iOS多线程----NSOperation 4.iOS多线程----GC...

  • iOS开发进阶-多线程技术

    iOS中多线程 首先看一道面试题 iOS中多线程有哪些实现方案? iOS中,多线程一般有三种方案GCD、NSOpe...

网友评论

      本文标题:iOS 多线程实现小结

      本文链接:https://www.haomeiwen.com/subject/vqeanttx.html