iOS多线程技术方案之NSThread

1,382 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

1. 简介

NSthread是苹果官方提供面向对象的线程操作技术,是对thread的上层封装,比较偏向于底层。简单方便,可以直接操作线程对象,使用频率较少。
创建线程的三种方式:

  • 通过init初始化方式创建,开辟线程,启动线程。
  • detach分离,不需要启动,直接分离出新的线程执行。
  • 隐式的多线程调用方法,没有thread,也没有start。所属NSObjectNSThreadPerformAdditions分类。
- (void)creatThreadMethod{ 
    NSLog(@"%@", [NSThread currentThread]); 
    
    //方式一:
    NSThread *t = [[NSThread alloc] initWithTarget:self.p selector:@selector(study:) object:@100]; 
    t.name = @"学习线程"; 
    [t start]; 
    
    //方式二:
    [NSThread detachNewThreadSelector:@selector(study:) toTarget:self.p withObject:@10000]; 
    
    //方式三: 
    [self.p performSelectorInBackground:@selector(study:) withObject:@5000]; 
    NSLog(@"%@", [NSThread currentThread]); 
}

1.1 属性

  • name:在应用程序中,收集错误日志,能够记录工作的线程。否则不好判断具体哪一个线程出的问题\
  • stackSize:该值必须以字节为单位,且为4KB的倍数\
  • isExecuting:线程是否在执行\
  • isCancelled:线程是否被取消\
  • isFinished:是否完成\
  • isMainThread:是否是主线程\
  • threadPriority:线程的优先级,取值范围0.0-1.0,默认优先级0.5。1.0表示最高优先级,优先级高CPU调度的频率高\
  • qualityOfService:服务质量,替代threadPriority属性\
- (void)testThreadProperty{ 
    // 主线程 512K 
    NSLog(@"NSThread:%@,stackSize:%zdK,isMainThread:%d", [NSThread currentThread], [NSThread currentThread].stackSize / 1024, [NSThread currentThread].isMainThread); 
    
    NSThread *t = [[NSThread alloc] initWithTarget:self selector:@selector(eat) object:nil]; 
    t.name = @"吃饭线程"; 
    t.stackSize = 1024*1024; 
    t.threadPriority = 1; 
    [t start]; 
}
------------------------- 
//输出以下内容: 
NSThread:<NSThread: 0x281014600>{number = 1, name = main},stackSize:512K,isMainThread:1

1.2 类方法

  • currentThread :获取当前线程
  • sleepForTimeInterval:阻塞线程
  • exit:退出线程
  • mainThread:获取主线程
- (void)threadTest{ 
    //当前线程
    [NSThread currentThread]; 
    // 如果返回值为1,表示主线程,否则是子线程 
    NSLog(@"%@", [NSThread currentThread]); 
    
    //阻塞休眠 
    [NSThread sleepForTimeInterval:2];//休眠时长,单位秒 
    [NSThread sleepUntilDate:[NSDate date]];//休眠到指定时间 
    //退出线程
    [NSThread exit]; 
    //判断当前线程是否为主线程 
    [NSThread isMainThread]; 
    //判断当前线程是否是多线程 
    [NSThread isMultiThreaded];
    //主线程的对象 
    NSThread *mainThread = [NSThread mainThread]; 
    NSLog(@"%@", mainThread); 
}

1.3 exit & cancel

  • exit:一旦强行终止线程,后续的所有代码都不会执行
  • cancel:取消当前线程,但是不能取消正在执行的线程
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ 
    [self testThreadStatus]; 
}
- (void)testThreadStatus{ 
    NSLog(@"%d %d %d", self.t.isExecuting, self.t.isFinished, self.t.isCancelled); 
    if ( self.t == nil || self.t.isCancelled || self.t.isFinished ) { 
        self.t = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil]; 
        self.t.name = @"跑步线程"; 
        [self.t start]; 
    }else{
        NSLog(@"%@ 正在执行",self.t.name);
        [self.t cancel]; self.t = nil; 
    }
}
- (void)run{ 
    NSLog(@"开始"); 
    // 下面的代码的作用是判断线程状态,可能因为下面的延时,阻塞会带来当前线程的一些影响 
    [NSThread sleepForTimeInterval:3]; 
    // 判断线程是否被取消 
    if ([NSThread currentThread].isCancelled) { 
        NSLog(@"%@被取消",self.t.name); 
        return; 
    }
    for (NSInteger i = 0; i < 10; i++) { 
        // 判断线程是否被取消 
        if ([NSThread currentThread].isCancelled) {
            NSLog(@"%@被取消",self.t.name); 
            return; 
        }
        if (i == 3) { 
            // 睡指定的时长(秒) 
            [NSThread sleepForTimeInterval:1]; 
        }
        NSLog(@"%@ %zd", [NSThread currentThread], i);
        // 内部取消线程 // 强制退出 - 当某一个条件满足,不希望线程继续工作,直接杀死线程,退出
        if (i == 8) {
            // 强制退出当前所在线程!后续的所有代码都不会执行
            [NSThread exit]; 
        }
    }
    NSLog(@"完成"); 
}