美文网首页iOS底层runtime.runloop
iOS 利用runloop阻塞主线程

iOS 利用runloop阻塞主线程

作者: 曾經蠟筆沒有小新 | 来源:发表于2021-03-16 18:35 被阅读0次

这里的阻塞主线程,并不是真正的卡死,而是利用runloop让主线程等待。

举例:我有三个方法需要依次执行testLogOne testLogTwo testLogThree,但是方法二testLogTwo中是有block或者是block 中有返回值的,方法三testLogThree需要等待方法二的block回调完成后才能执行。

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self testLogOne];
    [self testLogTwo:^{
        NSLog(@"----2----");
    }];
    [self testLogThree];
}

/// 方法一
- (void)testLogOne {
    NSLog(@"----1----");
}

/// 方法二
/// @param twoBlock 回调
- (void)testLogTwo:(void(^)(void))twoBlock {
    
    dispatch_async(dispatch_get_main_queue(), ^{
        if (twoBlock) {
            twoBlock();
        }
    });
}

/// 方法三
- (void)testLogThree {
    NSLog(@"----3----");
}

控制台输出

2021-03-16 18:04:41.691889+0800 demo[45188:559343] ----1----
2021-03-16 18:04:41.692060+0800 demo[45188:559343] ----3----
2021-03-16 18:04:41.714916+0800 demo[45188:559343] ----2----

使用信号量dispatch_semaphore_t ❌

使用信号量dispatch_semaphore_t会直接卡死主线程,永远等待不到信号的的接收。

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    /// 卡主线程
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    [self testLogOne];
    [self testLogTwo:^{
        NSLog(@"----2----");
        dispatch_semaphore_signal(semaphore);
    }];
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    [self testLogThree];
}

使用dispatch_group_t ⁉️

使用dispatch_group_t也可以将方法三testLogThree,放到dispatch_group_notify中执行,但是,考虑到实际情况下,其他方法可能要比方法三testLogThree先执行,所有也放弃了此用法的考虑。虽然可以将方法三testLogThree放到block中,但是如果有其他特殊情况,例如for循环,这样也是不可取的。

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    dispatch_group_t group = dispatch_group_create();

    [self testLogOne];

    for (NSInteger i = 0; i < 10; i ++) {
        dispatch_group_enter(group);
        [self testLogTwo:^{
            NSLog(@"----2----");
            dispatch_group_leave(group);
        }];
    }

    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"----2----after");
        //[self testLogThree];
    });

    [self testLogThree];
}

控制台输出

2021-03-16 18:15:47.571770+0800 demo[48810:577013] ----1----
2021-03-16 18:15:47.572034+0800 demo[48810:577013] ----3----
2021-03-16 18:15:47.588403+0800 demo[48810:577013] ----2----
2021-03-16 18:15:47.588557+0800 demo[48810:577013] ----2----
2021-03-16 18:15:47.588653+0800 demo[48810:577013] ----2----
2021-03-16 18:15:47.588736+0800 demo[48810:577013] ----2----
2021-03-16 18:15:47.588830+0800 demo[48810:577013] ----2----
2021-03-16 18:15:47.588919+0800 demo[48810:577013] ----2----
2021-03-16 18:15:47.589213+0800 demo[48810:577013] ----2----
2021-03-16 18:15:47.589303+0800 demo[48810:577013] ----2----
2021-03-16 18:15:47.589590+0800 demo[48810:577013] ----2----
2021-03-16 18:15:47.589831+0800 demo[48810:577013] ----2----
2021-03-16 18:15:47.590538+0800 demo[48810:577013] ----2----after

使用runloop ✅

运行runLoop一次,阻塞当前线程以等待处理。根据条件进行while循环,达到条件后runloop退出

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    __block BOOL isPerformNextStep = NO;

    [self testLogOne];


    for (NSInteger i = 0; i < 10; i ++) {
        [self testLogTwo:^{
            NSLog(@"----2----");
            isPerformNextStep = YES;
        }];
    }

    while (!isPerformNextStep) {
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }
    [self testLogThree];
}

控制台输出:

2021-03-16 18:30:12.403732+0800 demo[54758:602699] ----1----
2021-03-16 18:30:12.407238+0800 demo[54758:602699] ----2----
2021-03-16 18:30:12.407371+0800 demo[54758:602699] ----2----
2021-03-16 18:30:12.407472+0800 demo[54758:602699] ----2----
2021-03-16 18:30:12.407554+0800 demo[54758:602699] ----2----
2021-03-16 18:30:12.407631+0800 demo[54758:602699] ----2----
2021-03-16 18:30:12.407726+0800 demo[54758:602699] ----2----
2021-03-16 18:30:12.407801+0800 demo[54758:602699] ----2----
2021-03-16 18:30:12.407909+0800 demo[54758:602699] ----2----
2021-03-16 18:30:12.408005+0800 demo[54758:602699] ----2----
2021-03-16 18:30:12.408137+0800 demo[54758:602699] ----2----
2021-03-16 18:30:12.408383+0800 demo[54758:602699] ----3----

参考资料

iOS开发-阻塞主线程
IOS 等待条件满足再向下执行但不主卡线程NSRunLoop

相关文章

  • iOS 利用runloop阻塞主线程

    这里的阻塞主线程,并不是真正的卡死,而是利用runloop让主线程等待。 举例:我有三个方法需要依次执行testL...

  • RunLoop

    iOS刨根问底-深入理解RunLoop runloop 和线程有什么关系 iOS 多线程:RunLoop详细总结

  • GeekBand - iOS 多线程和RunLoop 总结

    iOS 开发高级进阶 第三周 多线程 Runloop iOS 多线程以及 RunLoop 学习总结 基础知识 什么...

  • iOS底层原理——浅谈RunLoop

    RunLoop应用:线程保活 线程保活、控制销毁 iOS-浅谈RunLoop8iOS底层原理总结 - RunLoo...

  • iOS之UIKit的布局和绘制

    整理对于iOS绘制和布局的知识。 一.iOS的主RunLoop iOS 的主 RunLoop 负责处理所有的用户输...

  • iOS 多线程:『RunLoop』详尽总结

    本文用来介绍 iOS 多线程中,RunLoop 的相关知识。主要包括如下内容:RunLoop 简介RunLoop ...

  • iOS-runloop相关

    本篇涵盖runloop解释、应用、利用runloop优化程序等. 1.iOS RunLoop漫谈2.RunLoop...

  • iOS RunLoop 详解

    转自 iOS RunLoop 详解 image.png Runloop 是和线程紧密相关的基础组件,是很多多线程有...

  • iOS-多线程相关

    本篇涵盖多线程解析、应用等. 1.iOS多线程--彻底学会多线程之『RunLoop』2.iOS多线程--彻底学会多...

  • Runloop相关探索

    Runloop 和 线程 在CFRunloop中已经说明了一个线程及其runloop的对应关系,现在以iOS中NS...

网友评论

    本文标题:iOS 利用runloop阻塞主线程

    本文链接:https://www.haomeiwen.com/subject/kowdcltx.html