多线程下关于NSTimer不释放的问题

多线程下关于NSTimer不释放的问题

前言

前段时间由于项目需要,用到NSTimer,考虑到不占用主线程资源,故把timer放在子线程运行。前几天发现该controller pop之后并没有释放,问题定位到NSTimer这里。经过测试发现NSTimer在多线程下不释放的问题,但是找不到原因。由于工作关系,未能继续进行问题定位追踪,所以先记录下来。若有同行看到并且有答案,望赐教。

正文

使用子线程创建NSTimer

代码:


- (void)createThread {

    self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(createTimer) object:nil];

    [self.thread start];

}


- (void)createTimer

{

    NSTimer *t = [NSTimer scheduledTimerWithTimeInterval:1.f target:self selector:@selector(repeat) userInfo:nil repeats:YES];

    self.timer = t;

    [[NSRunLoop currentRunLoop] run];

}


- (void)repeat

{

    NSLog(@"repeat --- ");

}


- (void)stopTimer

{

    [self.timer invalidate];

    self.timer = nil;

}

解开引用循环仍无法正常释放

如上代码,这里会循环引用,

self-->timer;

timer-->self;

self-->thread;

thread(RunLoop)-->timer。

理论上,在pop controller前调用- (void)stopTimer,self.timer会调用-(void)invalidate方法是的Timer对self的强引用解除,thread(RunLoop)对timer的强引用解除(详见invalidate的文档描述)。但是实际测试发现,调用- (void)stopTimer后虽然timer停止了,但是pop controller后,controller并没有释放。

在同一子线程执行- (void)stopTimer

查阅了一些资料,有这么一个说法:需在timer运行的线程下执行-(void)invalidate才有效果。抱着怀疑的态度(因为实际上,像上面的代码一样,在主线程调用,一样能使timer停止)在同一线程执行-(void)invalidate,如下代码:


[self performSelector:@selector(stopTimer) onThread:self.thread withObject:nil waitUntilDone:YES];

结果依旧是没有释放。

在timer的repeat中执行- (void)stopTimer

我也不知道为什么会做这样的尝试,或许是程序员的直觉吧。

于是在repeat中添加如下代码:


- (void)repeat

{

    static int i = 0;

    NSLog(@"repeat --- ");

    i++;

    if (i >=2) {

        [self.timer invalidate];

    }

}

这一试,我更凌乱了,controller能够正常释放。因为和上面尝试是一样在同一线程执行-(void)invalidate的,但这样controller能够正常释放。反复思量,我找不出两者的区别在哪里,所以我很凌乱。

结语

我并没有解决这个问题,在这里只是提出了一个问题,并且做了一些思考和尝试,可能是自己知识还有所欠缺,之后会找时间再去研究一下这个问题。

看到这里的你或许有答案,望赐教。

你可能感兴趣的:(多线程下关于NSTimer不释放的问题)