iOS多线程技术

原创 2015年11月18日 20:48:14

iOS多线程技术(多数用GCD)

(为了提高用户体验,把所有耗时的事情放到对等线程中,主线程中只做刷新UI界面的事情)

pthread 是 POSIX兼容的创建线程函数,是底层函数。

iOS有三种多线程编程技术:NSThread 、NSOperation 、GCD(实现负载均衡,多核cpu适合用它,以后的趋势是用GCD),它们的抽象程度由低到高,越高的使用起来越简单。

NSThread

显示调用NSThread类

  1. 类方法(创建完后立即启动线程)

    //创建一个线程,用NSThread这个类方法向 Target后面这个参数 发消息,这个对象在另外的线程中执行 @selector里面的方法  
    [NSThread detachNewThreadSelector:@selector(doSomething:)
    toTarget:self withObject:@"参数"];
  2. 实例方法(可以控制启动时间)

    NSThread *thread = [[NSThread alloc]initWithTarget:self
    selector:@selector(doSomething:) object:@"参数"];
    [thread start];

隐式调用

  1. 开启后台线程

     [“对象” performSelectorInBackground:@selector(doSomething:)
    withObject:@"参数"];
  2. 在主线程中运行(主线程是UI线程)(所有耗时的事情不能在主线程中进行)

    [“对象” performSelectorOnMainThread:@selector(doSomething:)
    withObject:@"参数" waitUntilDone:YES];
  3. 在指定线程中执行,但该线程必须具备run loop(需要“同步机制”的时候会用到)

    //对后一个参数表示 等待结束
      [“对象” performSelector::@selector(doSomething:) onThread:thread
    withObject:@"参数" waitUntilDone:YES];
    

常见NSThread的方法

```
+ (NSThread *)currentThread; //获得当前线程
+ (void)sleepForTimeInterval:(NSTimeInterval)ti; //线程休眠
+ (NSThread *)mainThread; //主线程(UI线程)
- (BOOL)isMainThread; //当前线程是否为主线程
+ (BOOL)isMainThread; //用NSThread类在某个线程中调用这个方法,判断是否为主线程
- (BOOL)isExecuting; //线程是否正在运行
- (BOOL)isFinished; //线程是否已经结束
```

NSOperation

(是一个抽象类,不能直接使用,要用他的子类,UIControl也是抽象类)

NSInvocationOperation

```
//创建一个队列
NSOperationQueue queue = [[NSOperationQueue alloc]init];
//创建子任务,定义子任务必须是NSOperation的子类
NSInvocationOperation operation = [[NSInvocationOperation alloc]initWithTarget:“消息接收者” selector:@selector(doSomething:) object:@"参数"];
//把当前任务添加到队列后,自动开启线程
[queue addOperation:operation];
```

NSBlockOperation

```
//创建一个队列
NSOperationQueue queue = [[NSOperationQueue alloc]init];
//创建NSBlockOperation对象
NSBlockOperation operation = [NSBlockOperation blockOperationWithBlock:^{[self doSomething];}]
//加入队列  
[queque addOperation:operation];
```

GCD(苹果开发的一个多核编程的解决方法)

一些重要的概念:

串行:一个事件(线程)被执行,另外的事件要等到它完成之后再执(队列的术语)
并发:一个事件(线程)被开启后,第二个事件就可以开启,不用等待前面事件的完成(队列的术语)(cpu还是单核情况下,对线程进行快速切换)
队列只有串行和并发两种形式

并行:两个事件(线程)同时进行,依赖于多个cpu(多核系统)
如果是并行,那么一定是并发,但是若果是并发,不一定是并行

同步:程序中我们调用一个了函数(线程),要等待它执行完了之后再执行下面的语句(派发的术语)
异步:程序中我们调用一个了函数(线程),不等待它执行完了之后就执行下面的语句(派发的术语)

临界区:是一段代码,它可能进行并发访问(多个进程同时访问这段代码)(临界区需要加锁)

竞态条件:多个进程对共享的数据进行读或写的操作时,最终的结果取决于这些进程的执行顺序

死锁:多个进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。(建议在多线程中访问相同的多个数据时,按照相同的顺序进行)

线程安全:线程安全就是多线程访问同一代码,不会产生不确定的结果(与类相关,这个类在创建的时候要不要加锁)。不可变的对象一般是线程安全的,主线程用来处理事件。对于苹果官方的类,可变的类是线程不安全的(例如:NSMutableString,NSMutableArray)
iOS开发环境:Cocoa touch

GCD的工作原理

通过队列的形式来实现线程(系统提供一个主队列(串行),四个并发队列),每一个队列就是一个block块,建立在任务并行执行的线程池模式的基础上。

GCD的底层依然是用线程实现。

GCD中的队列称为dispatch queue(派遣队列),它可以保证先进来的任务先得到执行。
dispatch queue(分发队列)分为下面三种:

  1. Serial(串行) ,
又称为private dispatch queues,同时只执行一个任务串行。Serial queue通常用于同步访问特定的资源或数据。当你创建多个Serial queue时,虽然它们各自是同步执行的,但Serial queue与Serial queue之间是并发执行的。
  2. Concurrent(并发) ,
又称为global dispatch queue,可以并发地执行多个任务,但是执行完成的顺序是随机的。
  3. Main dispatch queue ,
它是全局可用的串行队列,它是在应用程序主线程上执行任务的。

创建队列

第一个参数代表队列的标识符(是一个c风格的字符串),第二个参数代表队列的类型(DISPATCH_QUEUE_CONCURRENT创建并发队列,DISPATCH_QUEUE_SERIAL是创建串行队列)(返回值是dispatch_queue_t类型)   
dispatch_queue_t dispatch_queue_create( const char *label dispatch_queue_attr_t attr);

获取系统定义的全局并发队列

第一个参数表示优先级(优先级最好不要随意更改,否则会造成优先级反转),第二个参数目前没有使用,设置为0   
dispatch_queue_t dispatch_get_global_queue( long identifier, unsigned long flags
//四种优先级
#define DISPATCH_QUEUE_PRIORITY_HIGH   #define DISPATCH_QUEUE_PRIORITY_DEFAULT   #define DISPATCH_QUEUE_PRIORITY_LOW     #define DISPATCH_QUEUE_PRIORITY_BACKGROUND

获取主队列
dispatch_queue_t dispatch_get_main_queue(void);

向一个队列里面派发线程

  1. 异步派发(第一个参数代表要派发到哪个队列,第二个参数代表用block表示的线程)
    void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
  2. 同步派发
    void dispatch_sync( dispatch_queue_t queue, dispatch_block_t block);

大多数情况下多线程的代码模版

//把耗时的操作异步派发到默认优先级的并发队列
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 耗时的操作
dispatch_async(dispatch_get_main_queue(), ^{
// 更新UI界面
});
});

//如果最后一个线程和前几个线程有依赖关系,就把前几个线程放到组中
//创建组
dispatch_group_t dispatch_group_create( void );
//异步派发到组里面
void dispatch_group_async( dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block);
//组里面的程序执行完后,在外面获取通知,继续执行
void dispatch_group_notify( dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block);

补充

//第一个参数表示被放到队列中的代码块要被重复执行几次,后面的参数是队列和代码块(这个方法是同步返回,也就是说等到所有block执行完毕才返回)
void dispatch_apply( size_t iterations, dispatch_queue_t queue, void (^block)( size_t));
//延迟执行block块,第一个参数表示时间
void dispatch_after( dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block);
//初始化单例的时候会使用到,(避免临界区访问)这个方法是对加锁的封装,第一个参数表示dispatch_once_t类型变量(必须使用全局变量或静态变量,最好使用静态变量)的指针
void dispatch_once( dispatch_once_t *predicate, dispatch_block_t block);

查看官方文档的时候,如果有 Discussion 就一定要看下,里面是我们经常会犯的错误

初始化单例的固定模式:

+ (instancetype)sharedInstance{
    static QYSomeClass *manager;
    static dispatch_once_t once;//创建dispatch_once_t类型的静态变量
    dispatch_once(&once, ^{
        manager = [[QYSomeClass alloc]init];//这里面的代码只会执行一次
    });
    return manager;
}

障碍

障碍都是放到自定义的并发队列中,因为串行队列中本身就是一步步执行

障碍可以用做读写锁,放置一个文件被同时读写

//设置同步执行的block,它会等到在它加入队列之前的block执行完毕后,才开始执行。在它之后加入队列的block,则等到这个block执行完毕后才开始执行(异步返回函数)
void dispatch_barrier_sync( dispatch_queue_t queue, dispatch_block_t block);
//同上(同步返回函数)
void dispatch_barrier_sync(dispatch_queue_t queue, dispatch_block_t block); 

死锁

两个被派发的任务互相等待,程序无法继续向下执行,形成死锁

在一个串行队列里面,一个异步派发的任务(线程)中,再去同步地派发一个任务(线程),必然死锁,举例如下:

//创建一个串行队列
    dispatch_queue_t queue = dispatch_queue_create("com.qingyun.serial", DISPATCH_QUEUE_SERIAL);
//1和2互相等待,形成死锁,只有1打印出来了,后面的都没出来
    dispatch_async(queue, ^{
        NSLog(@"1 job");
        dispatch_sync(queue, ^{
            NSLog(@"2 job");
        });
    });
版权声明:本文为博主原创文章,未经博主允许不得转载。

iOS开发之多线程技术(NSThread、OperationQueue、GCD)

在前面的博客中如果用到了异步请求的话,也是用到的第三方的东西,没有正儿八经的用过iOS中多线程的东西。其实多线程的东西还是蛮重要的,如果对于之前学过操作系统的小伙伴来说,理解多线程的东西还是比较容易的...

iOS开发之多线程技术(NSThread、OperationQueue、GCD)

在前面的博客中如果用到了异步请求的话,也是用到的第三方的东西,没有正儿八经的用过iOS中多线程的东西。其实多线程的东西还是蛮重要的,如果对于之前学过操作系统的小伙伴来说,理解多线程的东西还是比较容易的...

iOS三种多线程技术NSThread,NSOperation/NSOperationQueue,GCD-Grand Central Dispatch

一.NSThread 建立一个线程方便,但是要使用NSThread管理多个线程非常困难,只要记住以下几个方法. (1) [NSThread currentThread] //跟踪任务所在线程,适用于这...

iOS的三种多线程技术

1.iOS的三种多线程技术1.NSThread 每个NSThread对象对应一个线程,量级较轻(真正的多线程) 2.以下两点是苹果专门开发的“并发”技术,使得程序员可以不再去关心线程的具体使用问题 ...

iOS多线程技术

原文章点此多线程技术我们为何需要多线程呢?多线程其实是为了实现并发执行,而且线程是并发执行多个代码路径的多种技术之中比较轻量级的一种(对应较重的实现是多进程)。在单核 CPU 时代,支持多线程的操作系...

IOS多线程技术详解

并发所描述的概念就是同时运行多个任务。这些任务可能是以在单核 CPU 上分时(时间共享)的形式同时运行,也可能是在多核 CPU 上以真正的并行方式来运行。OS X 和 iOS 提供了几种不同的 API...

OS X 和 iOS 中的多线程技术

多线程技术 我们为何需要多线程呢?多线程其实是为了实现并发执行,而且线程是并发执行多个代码路径的多种技术之中比较轻量级的一种(对应较重的实现是多进程)。 在单核 CPU 时代,支持多线程的操作系统会通...

iOS的三种多线程技术 对比分析

1.iOS的三种多线程技术                     1.NSThread 每个NSThread对象对应一个线程,量级较轻(真正的多线程) 2.以下两点是苹果专门开发的“并发...

iOS- 多线程技术的概述及优点

//判断101-200之间有多少个素数,并输出所有素数。 void fun_sushu(); void fun_sushu(){ int i,j; for (i=101; i...

OS X 和 iOS 中的多线程技术

[-] 多线程技术Objective-C 中实现多线程 performSelectorsNSThreadNSOperationGCD GCD 分发队列 串行分发队列Serial...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:iOS多线程技术
举报原因:
原因补充:

(最多只允许输入30个字)