多线程编程

2019-02-28  本文已影响0人  陌巷先森

一、多线程的基本概念:

二、多线程的解决方案

在iOS中,目前有4套解决方案:pthreads,NSThread,GCD,NSOperation;

Pthreads

这是一套基于C语言的多线程API,适用于Unix/Liunx/Windows等系统,可移植性强,但使用难度大。

NSThread

这套方案是经过苹果封装后,完全面向对象的。可以直接操控线程对象,但是生命周期需要手动管理。
NSThread有三种创建方式:
init方式,需要手动启动

- (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
- (instancetype)initWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

detachNewThreadSelector创建好之后自动启动

+ (void)detachNewThreadWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;

performSelectorInBackground创建好之后也是直接启动

- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

NSOperation

1.NSOperation和NSOperationQueue

NSOperation是苹果对GCD的封装,完全面向对象,NSOperation和NSOperationQueue分别对应GCD中的任务和队列。
将要执行的任务封装到一个NSOperation对象中,将此任务添加到一个NSOperationQueue对象中,然后系统就会自动执行。

2.添加任务

NSOperation

NSOperation只是一个抽象类,不能直接使用。它提供了2个子类用于封装任务,分别是:NSInvocationOperation和NSBlockOperation。创建一个Operation后,需要调用start方法启动任务,默认在当前队列同步执行,取消任务时调用cancel方法。

- (nullable instancetype)initWithTarget:(id)target selector:(SEL)sel object:(nullable id)arg;
+ (instancetype)blockOperationWithBlock:(void (^)(void))block;
- (void)addExecutionBlock:(void (^)(void))block;
NSOperationQueue

NSOperationQueue只有两种队列:主队列、其他队列。其他队列包含了串行和并发。
NSOperationQueue中有个参数叫最大并发数:maxConcurrentOperationCount,默认为-1,直接并发执行,当为1时表示不开启新线程,串行执行。

GCD

1.GCD特点

GCD会自动利用更多的CPU内核
GCD自动管理线程的生命周期(创建线程,调度任务,销毁线程等)
程序员只需要告诉 GCD 想要如何执行什么任务,不需要编写任何线程管理代码

2.GCD的基本概念

3.创建队列

使用dispatch_queue_create来创建队列对象,传入两个参数,第一个参数表示队列的唯一标识,可为空。第二个参数用来表示串行队列(DISPATCH_QUEUE_SERIAL)或并发队列(DISPATCH_QUEUE_CONCURRENT)。

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

GCD还有另外两种队列:
主队列:用于刷新UI。

dispatch_get_main_queue()

全局并发队列:只要是并行任务一般都会加入到这个队列,这是系统提供的一个并发队列。

dispatch_get_global_queue(long identifier, unsigned long flags);

4.创建任务

同步任务:会阻塞当前线程,使用dispatch_sync创建

dispatch_sync(dispatch_queue_t queue, DISPATCH_NOESCAPE dispatch_block_t block);

异步任务:不会阻塞当前线程,使用dispatch_async创建

dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

5.GCD其他方法

当任务需要异步进行,但是这些任务需要分成两组来执行时,可以使用dispatch_barrier_async

dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);

当任务需要等待一段时间后执行时,可以使用dispatch_after

dispatch_after(dispatch_time_t when,
    dispatch_queue_t queue,
    dispatch_block_t block);

GCD中有个快速迭代的方法dispatch_apply,可以同时遍历多个数字。

dispatch_apply(size_t iterations, dispatch_queue_t queue,
        DISPATCH_NOESCAPE void (^block)(size_t));

异步执行几个耗时操作,当几个操作完成时回到主线程操作可以使用dispatch_group。所有队列组中的并发任务并不按照顺序执行,当操作都完成时会调用dispatch_group_notify函数。

dispatch_group_async(dispatch_group_t group,
    dispatch_queue_t queue,
    dispatch_block_t block);

三、多线程的其他用法

    __block int count = 0;
    //创建一个定时器
    __block dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
    //设置启动时间
    dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, 0);
    //设置定时器各项参数
     dispatch_source_set_timer(timer, start, (int64_t)(1.0 * NSEC_PER_SEC), 0);
    // 设置回调
    dispatch_source_set_event_handler(timer, ^{
        NSLog(@"%d----%@", count,[NSThread currentThread]);
        count++;
        if (count == 4) {
            // 取消定时器
            dispatch_cancel(timer);
            timer = nil;
            NSLog(@"定时器销毁");
        }
    });
    //启动定时器
    dispatch_resume(timer);
{
static Tool *_instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
_instance = [[Tool alloc] init];
});
return _instance;
}

参考:完整项目资料下载

上一篇下一篇

猜你喜欢

热点阅读