多线程一些理解

iOS多线程几种实现方案

1.pthread .   C语言但是使用难度大,用于Windows,Linux等平台,几乎不用

2.NSThread       OC 简单易用,直接操作线程对象,但是偶尔使用。

3.GCD    C语言  是为了替代NSThread等线程计数,充分利用设备多核,自动管理所以经常使用。

4.NSOperation   OC语言,基于GCD 自动管理,所以也是经常使用。

 

1.在pthread中要实现它的子线程,导入<pthread.h>,pthread_t thread;pthread_create($thread,NULL,函数名,NULL);实现函数方法,比如void * run(void *param){for 循环一下,return NULL;}

2.NSThread  

首先是创建线程 

- (void)viewDidLoad {
    [super viewDidLoad];
    NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(run:) object:nil];
    [thread start];
}
-(void)run:(NSString *)param{
    for (int i=0; i<10000; i++) {
        NSLog(@"%@--%@",param,[NSThread currentThread].name);
    }
}

启动线程

还有一种创建线程的方式

[self performSelectorInBackground:(nonnull SEL) withObject:(nullable id)] 

[self performSelectorOnMainThread:(nonnull SEL) withObject:(nullable id) waitUntilDone:(BOOL)]

以上都不是很完美的方式

/*******************************************************/

3.GCD


全称:Grand Central Dispatch  牛逼的中枢调度器

为多核并行解决方案,自动利用CPU内核。自动管理生命周期,不需要编写任何线程管理代码

两个核心概念:任务和队列

两个步骤:定制任务和添加任务

  //异步 具备开启新线程的能力
    dispatch_async(dispatch_queue_t queue, ^{
        code
    })
    //同
    dispatch_sync(dispatch_queue_t queue, ^{
        code
    })

queue 队列   block 任务

GCD队列的两大类型

并发队列 只有在异步才有效,多个任务并发执行

串行队列  一个任务完成后,才开始执行下一个任务

创建并发队列

dispatch_queue_t queue = dispatch_queue_create(const char *label, dispatch_queue_attr_t attr)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

多线程安全隐患

1.多个线程可能会访问同一块资源。比如多个线程访问同一个对象,同一个变量和文件。想象存钱和取钱的例子。会覆盖之前的数据,无法实时更新提示。

2.解决方案就是加一把锁。互斥锁。等一个线程访问完毕后就解除锁。@synchronized(锁对象self)但是它会消耗大量CPU资源。不建议使用

 

原子核非原子属性

nonatomic

非线程安全,适合内存小的移动设备,所以所有的属性声明都是nonatomic

尽量避免多线程抢夺同一资源

atomic

 原子属性 为setter方法,需要消耗大量资源

 

线程之间的通信

一个进程中,线程不是孤立 的,多个线程之间需要通信,比如在主线程中我们添加UI控件,图片等,在子线程中下载图片,下载完毕之后,要在主线程中显示图片

 

栅栏barrier,先执行前面的任务才执行后面的。

延迟执行: 

[self performSelector:(nonnull SEL) withObject:(nullable id) afterDelay:(NSTimeInterval)];

GCD延迟执行

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
    });

NSTimer

[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:NO];

一次性代码

使用dispatch_once保证某段代码在整个程序运行过程中只执行一次

static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
    });

 

GCD单例模式

设计模式

保证在程序运行时,一个类只有一个实例,而且该实例易于供外界访问。

使用场合

1.在整个引用程序中,共享一份资源(这份资源只需要创建初始化一次)

static id _instance;

+(instancetype)allocWithZone:(struct _NSZone *)zone
{
    @synchronized(self) {
        if (_instance == nil) {
            _instance = [super allocWithZone:zone];
        }
    }
    
    return _instance;
}
+(instancetype)sharedInstance
{
    @synchronized(self) {
        if (_instance == nil) {
            _instance = [[self alloc]init];
        }
    }
    
    return _instance;
}

-(id)copyWithZone:(NSZone *)zone
{
    return _instance;
}

 

 

利用宏写单例。

##代表替代的单例名称

\代表指针指向,强指针

#define XiaoSingleH(name) + (instancetype)shared##name;

#define XiaoSingleM\
static id _instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
    static dispatch_once_t onceToken;\
    dispatch_once(&onceToken, ^{\
        _instance = [super allocWithZone:zone];\
    });\
    return _instance;\
}\
+(instancetype)sharedInstance\
{\
    static dispatch_once_t onceToken;\
    dispatch_once(&onceToken, ^{\
        _instance = [[self alloc]init];\
    });\
    return _instance;\
}\
-(id)copyWithZone:(NSZone *)zone\
{\
    return _instance;\
}\

 

NSOperation

一、NSOperation简介

1.简单说明

NSOperation的作⽤:配合使用NSOperationNSOperationQueue也能实现多线程编程

NSOperationNSOperationQueue实现多线程的具体步骤:

1)先将需要执行的操作封装到一个NSOperation对象中

2)然后将NSOperation对象添加到NSOperationQueue

3)系统会⾃动将NSOperationQueue中的NSOperation取出来

4)将取出的NSOperation封装的操作放到⼀条新线程中执⾏

 2.NSOperation的子类

NSOperation是个抽象类,并不具备封装操作的能力,必须使⽤它的子类

使用NSOperation⼦类的方式有3种:

1NSInvocationOperation

2NSBlockOperation

3)自定义子类继承NSOperation,实现内部相应的⽅法

二、 具体说明

1.NSInvocationOperation子类

创建对象和执行操作:

1  //创建操作对象,封装要执行的任务
2     //NSInvocationOperation   封装操作
3     NSInvocationOperation *operation=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test) object:nil];
4     
5     //执行操作
6     [operation start];

操作对象默认在主线程中执行,只有添加到队列中才会开启新的线程。即默认情况下,如果操作没有放到队列中queue中,都是同步执行。只有将NSOperation放到一个NSOperationQueue,才会异步执行操作 .

 

3.NSOperationQueue

NSOperationQueue的作⽤:NSOperation可以调⽤start⽅法来执⾏任务,但默认是同步执行的

如果将NSOperation添加到NSOperationQueue(操作队列),系统会自动异步执行NSOperation中的操作

添加操作到NSOperationQueue中,自动执行操作,自动开启线程

 

一、并发数

1)并发数:同时执⾏行的任务数.比如,同时开3个线程执行3个任务,并发数就是3

2)最大并发数:同一时间最多只能执行的任务的个数。

3)最⼤大并发数的相关⽅方法

- (NSInteger)maxConcurrentOperationCount;

- (void)setMaxConcurrentOperationCount:(NSInteger)cnt; 

说明:如果没有设置最大并发数,那么并发的个数是由系统内存和CPU决定的,可能内存多久开多一点,内存少就开少一点。

注意num的值并不代表线程的个数,仅仅代表线程的ID

提示:最大并发数不要乱写(5以内),不要开太多,一般以2~3为宜,因为虽然任务是在子线程进行处理的,但是cpu处理这些过多的子线程可能会影响UI,让UI变卡。

 

二、队列的取消,暂停和恢复

 1)取消队列的所有操作

 - (void)cancelAllOperations;

提⽰:也可以调用NSOperation- (void)cancel⽅法取消单个操作

 2)暂停和恢复队列

- (void)setSuspended:(BOOL)b; // YES代表暂停队列,NO代表恢复队列

- (BOOL)isSuspended; //当前状态

3)暂停和恢复的适用场合:在tableview界面,开线程下载远程的网络界面,对UI会有影响,使用户体验变差。那么这种情况,就可以设置在用户操作UI(如滚动屏幕)的时候,暂停队列(不是取消队列),停止滚动的时候,恢复队列。

 

三、操作优先级

 1)设置NSOperationqueue中的优先级,可以改变操作的执⾏优先级

- (NSOperationQueuePriority)queuePriority;

- (void)setQueuePriority:(NSOperationQueuePriority)p;

 2)优先级的取值

NSOperationQueuePriorityVeryLow = -8L,

NSOperationQueuePriorityLow = -4L,

NSOperationQueuePriorityNormal = 0,

NSOperationQueuePriorityHigh = 4,

NSOperationQueuePriorityVeryHigh = 8 

说明:优先级高的任务,调用的几率会更大。

 

posted on 2016-08-09 21:10  小豌先生  阅读(246)  评论(0)    收藏  举报

导航