文档章节

多线程—等待线程执行完再执行其他操作

xiaobai1315
 xiaobai1315
发布于 2017/04/28 18:04
字数 622
阅读 18
收藏 0

平时工作中经常会遇到这种需求: 开启线程A,等待A中的操作全部完成后,才执行下面的操作。

解决办法:

NSRunLoop

dispatch_async(dispatch_get_global_queue(0, 0), ^{
       
        NSLog(@"sleep");
        [NSThread sleepForTimeInterval:3];
        NSLog(@"end sleep");
        
        isdone = YES;
    });
    
    while(!isdone){
        
        [[NSRunLoop currentRunLoop] NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }
    
    NSLog(@"3333333");
    
执行结果:
2017-04-28 17:02:49.678 newTest[4692:2108632] sleep
2017-04-28 17:02:52.685 newTest[4692:2108632] end sleep
2017-04-28 17:02:52.685 newTest[4692:2108575] 3333333

在做这个示例的时候,遇到一个问题: 我是在ViewDidLoad()方法中去执行上面这段代码的,运行的时候回先打印‘sleep’,然后等3S打印'end sleep', 但是 '3333333' 有时候会等很长时间才打印出来。 将 NSDefaultRunLoopMode 改成 NSRunLoopCommonModes 就可以立即打印出来。 有可能当前RunLoopMode 切换成了 NSRunLoopCommonModes,导致结果打印不出来; 通过调用 NSLog(@"%@",[NSRunLoop currentRunLoop]); 输出当前RunLoopMode,发现当前RunLoopMode确实是NSRunLoopCommonModes。

 common modes = <CFBasicHash 0x145603140 [0x1a154c150]>{type = mutable set, count = 2,
 
entries =>
    0 : <CFString 0x19d3a16e0 [0x1a154c150]>{contents = "UITrackingRunLoopMode"}
    2 : <CFString 0x19cb69020 [0x1a154c150]>{contents = "kCFRunLoopDefaultMode"}
}

在子线程中执行这段代码,可以正常输出结果

dispatch_async(dispatch_get_global_queue(0, 0), ^{

        
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
           
            NSLog(@"sleep");
            [NSThread sleepForTimeInterval:3];
            NSLog(@"end sleep");
            
            isdone = YES;
        });
        
        NSLog(@"%@",[NSRunLoop currentRunLoop]);

        while(!isdone){
            
            [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        }
        
        NSLog(@"3333333");
    
    });

子线程中的RunLoopMode是 NSDefaultRunLoopMode

common modes = <CFBasicHash 0x126e770d0 [0x1a154c150]>{type = mutable set, count = 1,
entries =>
    2 : <CFString 0x19cb69020 [0x1a154c150]>{contents = "kCFRunLoopDefaultMode"}
}

关于线程和RunLoop的关系,传送门

dispatch信号量

 //初始化信号量为0
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
       
        NSLog(@"sleep");
        [NSThread sleepForTimeInterval:3];
        NSLog(@"end sleep");
        
        //信号量+1
        dispatch_semaphore_signal(sema);

    });
    
    //信号量-1,如果信号量 < 0,继续等待;信号量 >=0 ,执行下面的操作
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    
    NSLog(@"3333333");
    
执行结果:
2017-04-28 17:02:49.678 newTest[4692:2108632] sleep
2017-04-28 17:02:52.685 newTest[4692:2108632] end sleep
2017-04-28 17:02:52.685 newTest[4692:2108575] 3333333

NSOperation

//NSOperationQueue +  NSBlockOperation

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    NSBlockOperation *ope = [NSBlockOperation blockOperationWithBlock:^{
        
        [NSThread sleepForTimeInterval:3];
        NSLog(@"sleep");
        [NSThread sleepForTimeInterval:3];
        NSLog(@"end sleep");
    }];
    
    [queue addOperations:@[invo] waitUntilFinished:YES];
        
    NSLog(@"3333333");
    
输出结果:
2017-04-28 16:36:54.247 newTest[4663:2100420] sleep
2017-04-28 16:36:57.249 newTest[4663:2100420] end sleep
2017-04-28 16:36:57.250 newTest[4663:2100375] 3333333
//NSOperationQueue +  NSInvocationOperation
使用NSInvocationOperation的好处是,可以获取selector的执行结果;

    - (void)viewDidLoad {
    [super viewDidLoad];
    
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    NSInvocationOperation *ope = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(showmsg) object:nil];
    
    [queue addOperations:@[ope] waitUntilFinished:YES];
    
    NSLog(@"%@", ope.result);
    
    NSLog(@"3333333");
    
}

-(NSNumber *)showmsg
{
    NSLog(@"sleep");
    [NSThread sleepForTimeInterval:3];
    NSLog(@"end sleep");
    return @100;
}

输出结果:
2017-04-28 16:38:39.380 newTest[4667:2100951] sleep
2017-04-28 16:38:42.383 newTest[4667:2100951] end sleep
2017-04-28 16:38:42.384 newTest[4667:2100926] 100
2017-04-28 16:38:42.384 newTest[4667:2100926] 3333333

© 著作权归作者所有

共有 人打赏支持
xiaobai1315
粉丝 3
博文 197
码字总数 80276
作品 0
程序员
iOS开发系列--并行开发其实很容易

--多线程开发 概览 大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算。可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行。但是机器...

jianxin160
2015/08/18
0
0
iOS开发--多线程 并行开发

概览 大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算。可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行。但是机器码是按顺序执...

黑伞将军
2015/09/15
58
0
多线程(四)

多线程的学习真的接近尾声了,真幸运,走到这步蛮不容易的,总觉得应该多写点什么,算了吧!还是记录下有关多线程方面的知识点吧! 停止线程 如何停止线程呢?须知stop()已经过时,那就只有一...

yerenyuan_pku
2017/10/09
0
0
iOS下的并行开发

在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算。可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行。但是机器码是按顺序执行的,一个复杂的多...

iShown
2016/07/01
0
0
Java学习笔记--线程和多线程线程池(简单理解)

线程: 单核的cpu在一个时间片中只能执行一个应用程序 各个程序其实在做cpu的资源真多战而已 cpu做了快速的切换动作 疑问 :线程负责了代码 的执行,我们之前没有学过线程,为什么代码可以执...

codingcoge
05/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

函数调用约定 (cdecl stdcall)

函数调用约定 (cdecl stdcall) 在 C 语言里,我们通过阅读函数声明,就知道怎么携带参数去调用函数,也能在函数体定义内使用这些参数。但是 CPU 并不直接完成函数调用的传参操作,这需要人为...

傅易
5分钟前
0
0
Python 核心编程 (全)

浅拷贝和深拷贝 1.浅拷贝:是对于一个对象的顶层拷贝,通俗的理解是:拷贝了引用,并没有拷贝内容。相当于把变量里面指向的一个地址给了另一个变量就是浅拷贝,而没有创建一个新的对象,如a=b...

代码打碟手
8分钟前
0
0
mysql5.7 修改datadir

mysql 的默认存储路径为 /var/lib/mysql ,修改后为 /data/mysql 关闭服务 service mysql stop 复制mysql 数据文件到新的目录 cp -rp /var/lib/mysql /data 查看原目录的权限,如果新目...

hotsmile
24分钟前
0
0
证书安装指引之Tomcat 证书部署

Tomcat 证书部署 0 申请证书 1 获取证书 如果申请证书时有填写私钥密码,下载可获得Tomcat文件夹,其中有密钥库 www.domain.com.jks; 如果没有填写私钥密码,证书下载包的Tomcat文件夹中包括...

吴伟祥
29分钟前
0
0
ConcurrentHashMap1.7和1.8的底层不同实现

1.Hashmap和HashTable在线程安全方面的优劣? Hashmap多线程会导致HashMap的Entry链表形成环形数据结构,一旦形成环形数据结构,Entry的next节点永远不为空,就会产生死循环获取Entry。 Hash...

刘祖鹏
44分钟前
9
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部