iOS底层系列之<32>--多线程<二>和RunLoop一起使用

发布于:2023-02-03 ⋅ 阅读:(217) ⋅ 点赞:(0)

1、GCD和RunLoop一起使用

  • 下面打印结果是什么?
- (void)test4 {
    NSLog(@"3");
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0 );
    
    dispatch_async(queue, ^{
        NSLog(@"1");
        [self performSelector:@selector(test4) withObject:nil afterDelay:0.0];
        NSLog(@"2");

        NSLog(@"--end");
    });
}

打印结果:

2022-01-25 16:30:45.631871+0800 gcd[26764:2852276] 1

2022-01-25 16:30:45.632006+0800 gcd[26764:2852276] 2

2022-01-25 16:30:45.632075+0800 gcd[26764:2852276] --end

  • 为什么任务3不打印呢?

因为[self performSelector:@selector(test4) withObject:nil afterDelay:0.0];这句代码是往RunLoop中添加了定时器,然而,全局队列下的异步函数是开启了一个子线程,子线程是默认不会开启RunLoop的,需要手动开启RunLoop

如下修改:

- (void)test4 {
    NSLog(@"3");
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0 );
    
    dispatch_async(queue, ^{
        NSLog(@"1");
        [self performSelector:@selector(test4) withObject:nil afterDelay:0.0];
        NSLog(@"2");
        
        [[NSRunLoop currentRunLoop] addPort:[[NSPort port] init] forMode:NSDefaultRunLoopMode];
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        NSLog(@"--end");
    });
}

打印结果:(没有打印end)

2022-01-25 16:35:47.531165+0800 gcd[26952:2855439] 1

2022-01-25 16:35:47.531317+0800 gcd[26952:2855439] 2

2022-01-25 16:35:47.531435+0800 gcd[26952:2855439] 3

2、NSThread和RunLoop

下面代码打印是什么?

- (void)test5 {
    NSLog(@"5");
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    NSThread *thread = [[NSThread alloc] initWithBlock:^{
        NSLog(@"1%@",[NSThread currentThread]);
    }];
    [thread start];
    
    [self performSelector:@selector(test5) onThread:thread withObject:nil waitUntilDone:YES];
}

执行完了任务1后,会崩溃,因为往子线程thread中再次添加任务的时候,子线程已经自动销毁了,线程没有被保活

解决方案,让线程保活!

- (void)viewDidLoad {
    [super viewDidLoad];
}

- (void)test5 {
    NSLog(@"5");
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    NSThread *thread = [[NSThread alloc] initWithBlock:^{
        NSLog(@"1%@",[NSThread currentThread]);
        [[NSRunLoop currentRunLoop] addPort:[[NSMachPort port] init] forMode:NSDefaultRunLoopMode];
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }];
    [thread start];
    
    [self performSelector:@selector(test5) onThread:thread withObject:nil waitUntilDone:YES];
}

Foundation框架源码学习:GNUStep:GNUstep: Download

也可以参考这个​​​​​​​