iOS 常见问题汇总iOS开发坑点Fuck iOS EveryDay

一个线程问题

2018-11-02  本文已影响2583人  天下林子

----11月01 未整理好----
一个注意点:定时器repeats=YES,如果放在子线程中运行(需要开启线程runloop),当self.timer取消并释放的时候 这个子线程还是会被占用着,如下面apisQueue为串行队列,如何不打开注释行,之后清理timer,apisQueue添加的任务还是会一直处于等待状态

image.png

timer 消除之后变成了常驻线程,应将 runloop stop

还有一个问题是如果是常驻线程,那么首先往队列里添加一个repeat的定时器任务,然后再往队列里加任务1、2、3,对于这些任务1、2、3能不能被执行,又要怎样执行呢?
由于是串行队列 任务一直没有结束 所以后面的任务一直处于等待状态

timer结束 但是任务没有被结束runloop还开启者

参考图


image.png

所以重点是在于当前队列被[runloop run]阻塞了
repeats:NO时 执行完runloop run会停掉的(排除主线程
runloop就是一个消息循环,他必须要阻塞线程才能够实现消息处理,所以要注意什么线程开启循环就必须要停止。
并行只是不会阻塞,但是loop依然存在,线程还是不会释放的。而且还真没在并行线程上做过runloop
如果用到常驻线程 那你不要用队列获取线程 直接NSThread一个线程处理
最好不要使用“队列开辟”出来的线程进行常驻线程,串行队列或并行队列都应该规避,最好是自己创建一个线程变成常驻

image.png image.png

实例代码:

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, strong) dispatch_queue_t apisQueue;

@property (nonatomic, strong) NSTimer *timer;

@end

@implementation ViewController
{
    CFRunLoopRef _cfRunLoop;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    // 串行队列
    _apisQueue = dispatch_queue_create("MobPushApisQueue", DISPATCH_QUEUE_SERIAL);
    [self test];
}

- (void)test
{
    if ([self.timer isValid])
    {
        [self.timer invalidate];
    }
    self.timer = nil;
    __weak typeof(self) weakSelf = self;
    // 串行队列
    dispatch_async(self.apisQueue, ^{
            weakSelf.timer =  [NSTimer scheduledTimerWithTimeInterval:3
                                                               target:weakSelf
                                                             selector:@selector(_functionTest)
                                                             userInfo:nil
                                                              repeats:YES];
        //self->_cfRunLoop = CFRunLoopGetCurrent();
        [[NSRunLoop currentRunLoop] addTimer:weakSelf.timer forMode:NSRunLoopCommonModes];
        [[NSRunLoop currentRunLoop] run];
    });
}

- (void)_functionTest
{
    NSLog(@"_functionTest 线程:%@",[NSThread currentThread]);
}

- (IBAction)addTast:(id)sender
{
    NSLog(@"添加任务!");
    dispatch_async(self.apisQueue, ^{
        NSLog(@"执行了添加的任务 线程:%@",[NSThread currentThread]);
    });
}

- (IBAction)clearTimer:(id)sender
{
    if ([self.timer isValid])
    {
        [self.timer invalidate];
    }
    self.timer = nil;
    //CFRunLoopStop(_cfRunLoop);
    NSLog(@"clear timer");
}

@end

打印结果:

2018-11-02 09:44:36.166270+0800 TestDispatchQueue[6209:1193949] libMobileGestalt MobileGestalt.c:890: MGIsDeviceOneOfType is not supported on this platform.
2018-11-02 09:44:39.265693+0800 TestDispatchQueue[6209:1194388] _functionTest 线程:<NSThread: 0x600001cfc280>{number = 3, name = (null)}
2018-11-02 09:44:42.264495+0800 TestDispatchQueue[6209:1194388] _functionTest 线程:<NSThread: 0x600001cfc280>{number = 3, name = (null)}
2018-11-02 09:44:45.264686+0800 TestDispatchQueue[6209:1194388] _functionTest 线程:<NSThread: 0x600001cfc280>{number = 3, name = (null)}
2018-11-02 09:44:48.264508+0800 TestDispatchQueue[6209:1194388] _functionTest 线程:<NSThread: 0x600001cfc280>{number = 3, name = (null)}
2018-11-02 09:44:48.367080+0800 TestDispatchQueue[6209:1193949] 添加任务!
2018-11-02 09:44:50.267209+0800 TestDispatchQueue[6209:1193949] clear timer

参考链接在这:https://github.com/ChenYilong/iOSBlog/issues/9

避免使用 GCD Global队列创建Runloop常驻线程 https://blog.csdn.net/intheair100/article/details/81206265

上一篇 下一篇

猜你喜欢

热点阅读