Run loop和Thread

28 March 2014

Run-loop是什么?

首先考虑这个问题:你的Cocoa程序大部分的时间什么都没做,更具体点,是在等待输入。然而,一旦你触摸屏幕,相应的事件被触发,就可能会执行你的一段事件处理代码。同理,socket中返回一些数据,或者计时器触发等也是一样的情况。而且更重要的是,一旦触发事件的代码执行完,程序就会回到等待状态。在很多情况下,代码执行的时间要远小于程序等待输入的时间。

我认为run loop就是较好的利用了这个事实的一种机制。一个run loop就是跑在单个线程上进行事件处理的循环。你在run loop上注册输入源,并指定当这些源有输入时应该执行的代码。当特定的源上有输入时,run loop就会执行对应的代码,然后继续等待下一个输入事件。如果在run loop正在执行处理代码时,另外一个源的输入到了,run loop会在执行完正当前的处理后处理这个输入事件。好处是虽然你不知道具体的输入顺序,但你知道它们最终会一个接一个地被串行处理。这就是说你不会遇到多线程的问题,这也是run loop非常有用的原因。

和线程的关系?

每个线程,包括应用的主线程都有一个相关联的run loop对象,在应用中你不需要显式的创建run loop对象。在Carbon和Cocoa应用中,主线程会自动设置并运行它的run loop,这个过程也是应用启动过程的一部分。

Run loop的使用

默认情况下,iPhone上的所有触摸事件都会被main run loop放在队列里等待处理,所以你不需要对UI组件做额外的事情,而其他输入源需要一些额外的编码。比如在run loop上schedule一个NSInputStream,你需要像下面这样:

[iStream setDelegate:self];
[iStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

在上面的代码中,一旦iStream有输入数据,就会执行selfstream:handleEvent的方法。而且这个stream可以是任意类型的输入源,包括socket.

另外,timer对象也可以被schedule在run loop上,比如:

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

上面的代码把计时器schedule到当前的run loop上,每2秒就会调用selfdoStuff方法。

不适用run loop的情况

那什么时候不适合使用run loop呢?根据run loop的特点,输入事件会一个接一个的被串行处理,那么如果一个事件的处理需要的时间特别长的话,就会导致在这个事件处理完之前,app无法响应别的输入事件。在这种情况下,新开一个线程处理更合适。 然而,大部分情况下,我们的代码处理屏幕、socket或者计时器事件都非常快,这时使用main run loop处理起来更简单,也更安全。

编译自Run-loops vs. Threads in Cocoa

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Android的C++类Thread中,调用`run()`函数后,会执行一次`threadLoop()`函数,然后退出线程。如果需要循环执行`threadLoop()`函数,需要在自定义的线程类中重写`threadLoop()`函数,并在函数中添加循环逻辑。 以下是`Thread`类中`run()`函数的部分源码: ```cpp status_t Thread::run(const char* name, int32_t priority, size_t stack) { Mutex::Autolock _l(mLock); if (mThread != 0) { return INVALID_OPERATION; } mExited = false; mNeedToExit = false; mName = name; mPriority = priority; mStackSize = stack; mRunning = true; pthread_attr_t attr; pthread_attr_init(&attr); if (stack) { pthread_attr_setstacksize(&attr, stack); } int result = pthread_create(&mThread, &attr, _threadLoop, this); mSuccessfullyStartedException = (result == 0); pthread_attr_destroy(&attr); if (result == 0) { while (!mHasStarted) { mThreadExitedCondition.wait(mLock); } } else { mThread = 0; mRunning = false; mExited = true; mSuccessfullyStartedException = false; } return result; } ``` 可以看到,`run()`函数创建了一个新的线程,并调用`_threadLoop()`函数作为新线程的入口函数。在创建完线程后,`run()`函数会一直等待直到新线程成功启动,然后返回。 而在`_threadLoop()`函数中,会不断地调用用户自定义的`threadLoop()`函数,直到该函数返回为止。因此,如果需要循环执行`threadLoop()`函数,需要在自定义的线程类中重写`threadLoop()`函数并添加循环逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值