美文网首页多线程iOS多线程
iOS perfromSelector 和线程的关系

iOS perfromSelector 和线程的关系

作者: Edviin_2de8 | 来源:发表于2022-04-12 13:19 被阅读0次

perfromSelector:withObject: afterDelay:

image.png

问题

为什么不打印3

  • queue是个串行队列,async异步任务,会开辟一条新线程
  • 子线程默认不开启runloop
  • -(void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay; 其实就是在内部创建了 NSTimer ,然后添加到当前的runloop上面,因为子线程没有开启runloop 所以不会打印
  • 全局的并发队列也是在子线程中的
测试1
- (void)test2{
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"1");
        [[NSRunLoop currentRunLoop] run];
        [self performSelector:@selector(test) withObject:nil afterDelay:1];
        NSLog(@"3");
        NSLog(@"%@",[NSRunLoop currentRunLoop]);
    });
}
- (void)test{
    NSLog(@"2");
    
}

结果只会只会打印1 ,3 不会打印2

- (void)test2{
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"1");
        
        [self performSelector:@selector(test) withObject:nil afterDelay:5];
        [[NSRunLoop currentRunLoop] run];
        NSLog(@"3");
        NSLog(@"%@",[NSRunLoop currentRunLoop]);
    });
}
- (void)test{
    NSLog(@"2");
    
}

结果打印123

- (void)test2{
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"1");
        
        [self performSelector:@selector(test) withObject:nil afterDelay:5];
        NSLog(@"4");
        [[NSRunLoop currentRunLoop] run];
        NSLog(@"3");
//        NSLog(@"%@",[NSRunLoop currentRunLoop]);
    });
}
- (void)test{
    NSLog(@"2");
    
}

会打印1-4-2-4

总结

  • loop run 只是尝试开启当前线程的runloop,但是当前线程如果没有任何事件(source、timer、observer)的话,也并不会开启成功
  • performSelector 执行的线程就是当前的线程.
  • 没有提交当前的runloop的时候,是不会阻塞的,因为perform这个方法是在当前线程中执行的,所以当我们提交run的时候,检测到有source事件,也就是timer事件,会在当前线程阻塞去执行timer,当timer执行完毕之后,继续向下执行

performSelectorOnMainThread

- (void)test3{
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"1");
        
        [self performSelectorOnMainThread:@selector(test) withObject:nil waitUntilDone:YES];
        NSLog(@"3");
    });
}
- (void)test{
    NSLog(@"%@",[NSThread currentThread]);
    sleep(3);
    NSLog(@"2");
    
}

答案是 1,隔3秒然后打印2,在打印3

  • waitUntilDone:NO,这个参数只是决定是否阻塞当前线程,如果为YES,就需要等待任务结束后才可以向下执行,如果为NO,则不阻塞。
performSelectorInBackground

- (void)test4{
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"1");
        
        [self performSelectorInBackground:@selector(test) withObject:nil];
        NSLog(@"3");
    });
}
- (void)test{
    NSLog(@"%@",[NSThread currentThread]);
    sleep(3);
    NSLog(@"2");
    
}

打印结果为132,

  • 开辟一条新线程
  • 在子线程中执行,互不影响,不阻塞当前线程

performSelector:withObject

- (void)test5{
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"1");
        
        [self performSelector:@selector(test) withObject:nil];
        NSLog(@"3");
    });
}
- (void)test{
    NSLog(@"%@",[NSThread currentThread]);
    sleep(3);
    NSLog(@"2");
    
}

打印结果为123,
说明 performSelector:withObject 会阻塞当前线程,等方法执行完之后,才可以向下执行,
performSelector方法里面是同步的,如果有异步方法,也不会阻塞当前线程

相关文章

网友评论

    本文标题:iOS perfromSelector 和线程的关系

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