如何正确结束驱动RunLoop的NSThread

本文针对苹果官方给出的线程管理样例代码存在的缺陷进行了深入剖析,并提出了解决方案,包括如何避免内存泄漏及正确使用 CFRunLoop 来控制线程运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

不负责任的apple sample

Apple的Sample说可以轮循线程是否应该退出,但是有bug

see:documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html

- (void)threadRuntime:(id)arg
{
    @autoreleasepool {
        GXLog(@"Thread created............>>>>>>>>>>>>>>>>>>>>>>");
        NSRunLoop *rl = [NSRunLoop currentRunLoop];
        
        [_target performSelector:_selector withObject:arg];
        [_target release];
        _target = nil;
        
        BOOL exitNow = NO;
        NSMutableDictionary *threadDict = [[NSThread currentThread] threadDictionary];
        [threadDict setValue:[NSNumber numberWithBool:exitNow] forKey:@"ThreadShouldExitNow"];
        
        NSDate *date = [NSDate date];
        while (!exitNow) {
            [rl runUntilDate:date];
            exitNow = [[threadDict valueForKey:@"ThreadShouldExitNow"] boolValue];
        }

        [_thread release];
        _thread = nil;
        
        GXLog(@"Thread Exited............<<<<<<<<<<<<<<<<<<<<<<");
    }
}

Instruments进行Time Profile是这样的:


做的题外的修改,如果这样轮询

        while (!exitNow) {
            [rl runUntilDate:[NSDate date]];
            exitNow = [[threadDict valueForKey:@"ThreadShouldExitNow"] boolValue];
        }

内存占用很恐怖

[NSDate date] autorelease来不及释放,程序最终会因为内存耗尽被系统干掉。


使用CFRunLoopRun/CFRunLoopStop正确结束NSThread

一切皆因轮询而起,那就破了轮询

- (void)threadRuntime:(id)arg
{
    @autoreleasepool {
        GXLog(@"Thread created............>>>>>>>>>>>>>>>>>>>>>>");
        [_target performSelector:_selector withObject:arg];
        [_target release];
        _target = nil;
        
        CFRunLoopRun();
                
        [_thread release];
        _thread = nil;
        
        GXLog(@"Thread Exited............<<<<<<<<<<<<<<<<<<<<<<");
    }
}

- (void)stop
{
    if (!_thread) {
        return;
    }
    
    CFRunLoopStop(CFRunLoopGetCurrent());
}

千万小心,stop会直接停止当前线程得RunLoop,这要求在RunLoop所在的线程执行stop, 实际情况可能在其它线程调用stop。


小结

虽然cocoa&xcode有很多利器,但是能不用多线程还是别用吧。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值