iOS 如何保持线程一直在运转(二)

一、接着上一篇通过NSThread可以方便的创建一个线程,并且启动线程的Runloop,在线程体中执行一个while循环

  然后我们就可以方便得利用这个线程了

1
2
3
4
5
6
7
8
9
10
11
- (void)threadRun:(NSThread *)thread
{
    NSLog(@"Thread run");
    NSLog(@"hello 1");
    while (!_isCancelled && [currentRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]])
    {
        NSLog(@"hello 2");
        _isCancelled = [currentThread isCancelled];
    }
    NSLog(@"hello 3");
}

 

二、那我们应该如何正确结束一个NSThread呢

  NSThread结束可以调用两个方法,一个是对象方法-[Thread cancel],这个方法标记NSThraed的属性isCanceled为YES,那么通过配合上面的循环,线程体本身就结束了。

                  另外一个方法是+[Thread exit],注意这个方法需要在NSThraed为当前线程中调用,该方法比较暴力不管线程中的任务是否还在执行,

                                  直接结束,也不管runloop,因此可能带来内存泄露。

 

三、NSRunloop

  - (BOOL)runMode:(NSRunLoopMode)mode beforeDate:(NSDate *)limitDate;

  根据官方文档,上面的API在Runloop中没有事件源或者timer的时候,该方法会立即返回NO,所以在执行这个线程体的循环时候,需要先加入一个timer

  保证while循环不会结束,也就保证了线程不会结束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
- (void)threadRun:(NSThread *)thread
{
    NSLog(@"Thread run");
 
     
    _liveTimer = [NSTimer scheduledTimerWithTimeInterval:[[NSDate distantFuture] timeIntervalSinceNow]
                                     target:self
                                   selector:@selector(ignore:)
                                   userInfo:nil
                                    repeats:YES];
      
     
    NSThread *currentThread = [NSThread currentThread];
    NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];
     
    _isCancelled = [currentThread isCancelled];
 
    NSLog(@"hello 1");
    while (!_isCancelled && [currentRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]])
    {
        NSLog(@"hello 2");
        _isCancelled = [currentThread isCancelled];
        NSLog(@"hello 4");
    }
    NSLog(@"hello 3");
 
}

   上面的含义另外一层意思就是,只要循环结束,线程体结束,那么NSThread也就结束,NSThread中的Runloop也结束了,而不管Runloop中的什么事件有没有执行完

 那么一旦Runloop起来之后,将Runloop中的事件全部移除之后,Runloop是否会自动结束呢

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
- (void)stopThread:(NSThread *)thread
{
    //[self performSelector:@selector(stopThread:) withObject:thread afterDelay:5];
    [_liveTimer invalidate];
    //CFRunLoopStop(CFRunLoopGetCurrent());
    //[thread cancel];
    //_isCancelled = YES;
    //while ([thread isExecuting] == YES) usleep(10000);
    NSLog(@"stop done");
     
}
 
- (void)ignore:(NSTimer *)timer
{
    NSLog(@"ignore");
}
 
- (void)threadRun:(NSThread *)thread
{
    NSLog(@"Thread run");
     
     //占用0%的CPU
     
    _liveTimer = [NSTimer scheduledTimerWithTimeInterval:[[NSDate distantFuture] timeIntervalSinceNow]
                                     target:self
                                   selector:@selector(ignore:)
                                   userInfo:nil
                                    repeats:YES];
      
     
    NSThread *currentThread = [NSThread currentThread];
    NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];
     
    _isCancelled = [currentThread isCancelled];
 
     
    NSLog(@"hello 1");
    while (/*!_isCancelled && */[currentRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]])
    {
        NSLog(@"hello 2");
        //_isCancelled = [currentThread isCancelled];
        NSLog(@"hello 4");
    }
    NSLog(@"hello 3");
 
}

  上面的代码中去除了cancel标记,那么即使timer移除,这个while还在一直保持循环,因为- (BOOL)runMode:(NSRunLoopMode)mode beforeDate:(NSDate *)limitDate;不会返回第二次值

  那么如果没有while循环了呢,这个线程体也就真正结束啦

  

posted @   兜兜有糖的博客  阅读(671)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示