文档章节

NSRunloop的解析及autorelease的释放时机

刀客445
 刀客445
发布于 2016/05/19 17:17
字数 943
阅读 116
收藏 0

 

iOS的运行时是由一个一个runloop组成的,每个runloop都会执行下图所示的一些步骤:

每个runloop中都创建一个Autorelease Pool,并在runloop的末尾进行释放,
所以,一般情况下,每个接受autorelease消息的对象,都会在下个runloop开始前被释放。也就是说,在一段同步的代码中执行过程中,生成的对象接受autorelease消息后,一般是不会在代码段执行完成前释放的。

当然也有让autorelease提前生效的办法:自己创建Pool并进行释放

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

NSArray * array = [[[NSArray alloc] init] autorelease];

[pool drain];

上面的array就会在[pool drain]执行时被释放。

所以对于你遇到的问题,可以在for循环外嵌套一个Autorelease Pool进行管理,例如

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

for (int i = 0; i < 10000; i++)

{

    // ...

}

[pool drain];

但由于你提到了生成的每个实例可能会比较大。只在循环外嵌套,可能导致在pool释放前,内存里已经有10000个实例存在,造成瞬间占用内存过大的情况。

因此,如果你的每个实例仅需要在单次循环过程中用到,那么可以考虑可以在循环内创建pool并释放

for (int i = 0; i < 10000; i++)

{

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // ...

    [pool drain];

}


 

对于多线程来说,每一个线程都有自己的runloop, 主线程是默认开启的,创建的子线程要手动开启,因为NSApplication只启动main applicaiton thread

线程中没有source的runloop会自动结束。

事件由NSRunLoop 类处理。RunLoop监视操作系统的输入源,如果没有事件数据,不消耗任何CPU 资源。如果有事件数据,run loop 就发送消息,通知各个对象。

用 currentRunLoop 获得 runloop的 reference,给 runloop 发送run 消息启动它。

 

下面介绍四种情况是使用runloop的场合:

 1.使用端口或自定义输入源和其他线程通信

 2.子线程中使用了定时器

 3.cocoa中使用任何performSelector到了线程中运行方法

 4.使线程履行周期性任务,(我把这个理解与2相同)

如果我们在子线程中用了NSURLConnection异步请求,那也需要用到runloop,不然线程退出了,相应的delegate方法就不能触发。


 

这里通过小示例简单介绍以下有关runloop方面的问题:

1.首先简单运行执行runlooprun函数并不会让系统停住等待事件,而是需要在运行runloop之前添加source,只有在有source的情况下线程才会停下来监听各种事件。

2.runloop的使用:

1)生成一个runloop source

    // add send source

    CFRunLoopSourceContext  src_context ;

    NSError * emsg = nil ;

 

    // init send source context

    src_context.version = 0;

    src_context.info = inst;

    src_context.retain = NULL;

    src_context.release = NULL;

    src_context.copyDescription = NULL;

    src_context.equal = NULL;

    src_context.hash = NULL;

    src_context.schedule = NULL;

    src_context.cancel = NULL;

    src_context.perform = &callback ;//设置唤醒是调用的回调函数

 

    // create send source from context

 

   CFRunLoopSourceRef runloopSource ;

    runloopSource = CFRunLoopSourceCreate (NULL, 0, &src_context) ;

2)将source加入线程所属的runloop中

 

    // add the send source into  run loop

    CFRunLoopRef       threadRunLoop ;

    threadRunLoop =  CFRunLoopGetCurrent() ;

    CFRunLoopAddSource (threadRunLoop ,

                        runloopSource,

                        kCFRunLoopDefaultMode);

3)运行runloop

   CFRunLoopRun() ;


 

4)如何调用runloop(首先可以将各个线程的runloop和source保存起来)

 

   CFRunLoopSourceSignal(runloopSource) ;// 参数是你调用的runloop的source

   CFRunLoopWakeUp(threadRunLoop) ;//这句话的作用时立即执行该runloop的事件,如果没有这句话系统会在空闲的时候执行刚才的runloopSource相关的事件

3.如何停掉runloop退出线程

    CFRunLoopStop(threadRunLoop) ;这个函数可以停掉runloop是线程正常退出

4.ios整个系统基本上是基于runloop这种架构的,ios程序的main线程整体上也是基于runloop的,各种事件的响应应该也是基于source这种思路。

本文转载自:http://blog.csdn.net/xinruiios/article/details/8929915

共有 人打赏支持
刀客445
粉丝 2
博文 47
码字总数 10222
作品 0
杭州
私信 提问
NSRunloop,runloop,autoReleasePool和thread的关系理解及案例解决

1.NSRunloop NSRunloop顾名思义,就是一个消息循环,它会侦测输入源(input source)和定时源(timer source),然后做回调处理。这和windows的消息处理非常类似,只不过你无法看到类似SendMessa...

北方人在上海
2016/05/23
195
0
iPhone/Mac Objective-C内存管理教程和原理剖析 【四、系统自动创建新的autorelease pool】

四 系统自动创建新的autorelease pool 在生成新的Run Loop的时候,系统会自动创建新的autorelease pool(非常感谢网友hhyytt和neogui的提醒)。注意,此处不同于xcode在新建项目时自动生成的...

长平狐
2012/10/25
41
0
iPhone/Mac Objective-C内存管理教程和原理剖析(四)系统自动创建新的aut...

四 系统自动创建新的autorelease pool 在生成新的Run Loop的时候,系统会自动创建新的autorelease pool(非常感谢网友hhyytt和neogui的提醒)。注意,此处不同于xcode在新建项目时自动生成的...

Liuxz-aaa
2011/06/08
0
0
iPhone/Mac Objective-C内存管理教程和原理剖析

版权声明 此文版权归作者Vince Yuan (vince.yuan#gmail.com)所有。欢迎非营利性转载,转载时必须包含原始链接http://vinceyuan.cnblogs.com/,且必须包含此版权声明的完整内容。 版本 1.1 发...

黑衣李白
2012/12/27
0
0
对Objective-C内存管理策略的理解

Objective-C的内存管理策略是基于“拥有关系”的。凡是被“拥有”的对象,不会被回收。对内存的管理,实际上就是对“拥有”关系的管理。 通过开头名称为”alloc”,”new”,”copy”,”mutab...

nswish
2014/08/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Linux如何查看进程、杀死进程、启动进程等常用命令

关键字: linux 查进程、杀进程、起进程 1.查进程 ps命令查找与进程相关的PID号: ps a 显示现行终端机下的所有程序,包括其他用户的程序。 ps -A 显示所有程序。 ps c 列出程序时,显示每个程...

临江仙卜算子
12分钟前
1
0
ASP.NET Core MVC 静态文件配置

在启动文件中添加以下配置 public class Startup{ public IServiceProvider ConfigureServices(IServiceCollection services) { services.AddDirectoryBrowser(); ......

whltian
22分钟前
1
0
linux之自定义命令

本人使用的是ubuntu系统,不喜欢建各种桌面快捷链接,但是每次启动个软件,去查找又麻烦,所以自定义了命令,来快捷的启动应用: 1、修改/etc/bash.bashrc,在文件末尾,加上如下List-1中的内...

克虏伯
30分钟前
4
0
linux基础

系统安全 sudo su chmod setfacl 进程管理 w top ps kill pkill pstree killall 用户管理 id usermod useradd groupad userdel 文件系统 mount umount fsck df du 网络应用 curl telnet mail......

关元
31分钟前
4
0
Caffe-源码分析(一)

CHECK_X函数,用于比较两个blob之间的值 CHECK_EQ(x,y)<<"x!=y",EQ即equation,意为“等于”,当x!=y时,函数打印出x!=y。 CHECK_NE(x,y)<<"x=y",NE即not equation,意为“不等于”,,...

Pulsar-V
32分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部