博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS开发之Run Loop
阅读量:6268 次
发布时间:2019-06-22

本文共 2328 字,大约阅读时间需要 7 分钟。

1、概述

(1) Run Loop提供了一种异步执行代码的机制,不能并行执行任务。

(2) 在主队列中,Main Run Loop直接配合任务的执行,负责处理UI事件、计时器,以及其它内核相关事件。

(3) Run Loop的主要目的是保证程序执行的线程不会被系统终止。

Run Loop的工作特点:

(1) 当有事件发生时,Run Loop会根据具体的事件类型通知应用程序做出响应。

(2) 当没有事件发生时,Run Loop会进入休眠状态,从而达到省电的目的。

(3) 当事件再次发生时,Run Loop会被重新唤醒,处理事件。

主线程和其他线程中的Run Loop

iOS程序的主线程默认已经配置好了Run Loop,其他线程默认情况下没有设置Run Loop。

一般在开发中很少会主动创建RunLoop,而通常会把事件添加到RunLoop中。

loop示意图:

2UIApplication中的Run Loop

3多线程中的循环引用

如果self对象持有操作对象的引用,同时操作对象当中又直接访问了self时,才会造成循环引用。

单纯在操作对象中使用self不会造成循环引用。

注意:此时不能使用(weakSelf)

4、多线程中的资源共享

并发编程中许多问题的根源就是在多线程中访问共享资源。资源可以是一个属性、一个对象、网络设备或者一个文件等。

在多线程中任何一个共享的资源都可能是一个潜在的冲突点,必须精心设计以防止这种冲突的发生。

资源共享示例:

5互斥锁(@synchronized)

互斥锁使用注意:

(1)加互斥锁,在共享资源的“读”“写”范围添加互斥锁

(2)要让锁的范围尽可能小!

(3)资源抢夺做简单的做法就是使用互斥锁@synchronized

(4)使用互斥锁,会变慢,互斥锁的代价十分高昂!

加上互斥锁就可以使一个资源在同一时间只能被一个线程访问,只有这个资源被这个线程用完后其他线程才能访问。

互斥锁用法:

@synchronized(self) {

//线程操作

}

例如:

@interface MJViewController ()

@property (weak, nonatomic) IBOutlet UITextView *infoText;

// 票数,若使用原子锁,只需在互斥锁的基础上把下面nonatomic改为atomic即可

@property (nonatomic, assign) NSInteger tickets;

@end

 

@implementation MJViewController

 

- (void)viewDidLoad

{

    [super viewDidLoad];

}

 

// 卖票循环,一直卖完为止

- (void)doSaleLoop:(NSString *)opName

{

    // 所有线程进入都可以循环卖票

    while (YES) {

 

        @synchronized(self) {

            if (self.tickets > 0) {

                --self.tickets;

               

                NSLog(@"剩余票数 %d - %@ - %@", self.tickets, opName, [NSThread currentThread]);

            } else {

                break;

            }

        }

        //-----------------------------------------

        // 模拟休眠,跟资源抢夺无关,不用放在锁里

        if ([opName isEqualToString:@"OP 1"]) {

            [NSThread sleepForTimeInterval:1.0f];

        } else {

            [NSThread sleepForTimeInterval:0.3f];

        }

    }

}

 

#pragma mark 模拟多人卖票

#pragma mark GCD实现

 

- (IBAction)doSale:(id)sender

{

    // 做多线程开始时,永远不要相信一次运行的结果

    self.tickets = 20;

   

    // 1. 队列

    dispatch_queue_t q = dispatch_queue_create("sale", DISPATCH_QUEUE_CONCURRENT);

   

    // 2. 添加任务

    dispatch_async(q, ^{

        [self doSaleLoop:@"OP 1"];

    });

   

    dispatch_async(q, ^{

        [self doSaleLoop:@"OP 2"];

    });

   

    dispatch_async(q, ^{

        [self doSaleLoop:@"OP 3"];

    });

   

    dispatch_async(q, ^{

        [self doSaleLoop:@"OP 4"];

    });

}

 

@end

【备注】在iOS中还有一种锁的功能,原子锁 —— 多读单写的锁(128位自旋锁),也会消耗性能。

原子锁只保护写入时的数据正确,而读取不负责。

对于要写入的资源,保护“写入数据”的正确性重要,还是读取的准确性重要!

如果只是开发单写多读的功能,只需要使用原子锁即可。

@synchronized 性能消耗非常的大,苹果官方不建议使用。

在实际开发中,不要去抢夺资源!

*** 并发编程最主要的目的是提高性能,让更多的代码同时运行,达到并发运行,提高整体性能的目的!

*** 手机开发最主要的是流畅,并行,至于资源抢夺的功能开发是属于服务端的范畴!

 

转载于:https://www.cnblogs.com/lifengfneg/p/4774014.html

你可能感兴趣的文章
推荐科研软件
查看>>
gradle
查看>>
如何取消未知类型文件默认用记事本打开
查看>>
[Javascript] Immute Object
查看>>
Java 关于finally、static
查看>>
Posix mq和SystemV mq区别
查看>>
P6 EPPM Manual Installation Guide (Oracle Database)
查看>>
XMPP协议、IM、客户端互联详解
查看>>
PHP写文件函数
查看>>
mysql的sql_mode合理设置
查看>>
函数连续性与可导性
查看>>
linux下libevent安装
查看>>
用ip来获得用户所在地区信息
查看>>
卡尔曼滤波
查看>>
linux下面覆盖文件,如何实现直接覆盖,不提示
查看>>
CSS3阴影 box-shadow的使用和技巧总结
查看>>
Linux下高cpu解决方案
查看>>
SQL事务用法begin tran,commit tran和rollback tran的用法
查看>>
centos7 crontab笔记
查看>>
.Net AppDomain.CurrentDomain.AppendPrivatePath(@"Libs");
查看>>