iOS多线程技术方案之NSThread

语言: CN / TW / HK

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

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:{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(@"完成"); }