iOS开发之多线程(2)—— Thread

目录

  • 版本
  • 简介
  • 方法属性
  • 示例

版本

Xcode 11.5
Swift 5.2.2

简介

一个Thread即为一个线程.

方法属性

OC中的属性方法(Swift方法名类似):

#pragma mark - 属性 
// 可以使用返回的字典来保存线程的特定数据. (这只是一个普通的字典, 用来保存所有开发者感兴趣的数据.)
@property (readonly, retain) NSMutableDictionary *threadDictionary;
// 线程优先级
@property double threadPriority API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0)); // To be deprecated; use qualityOfService below
// 线程优先级 (枚举常量)
@property NSQualityOfService qualityOfService API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0)); // read-only after the thread is started
// 保存的线程名字 (不明觉厉)
@property (nullable, copy) NSString *name API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
// 线程的堆内存大小字节数 (必须是4KB的倍数, 要使设置有用, 必须在start方法调用前设置.)
@property NSUInteger stackSize API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
// 是否主线程
@property (readonly) BOOL isMainThread API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
// 线程是否在执行
@property (readonly, getter=isExecuting) BOOL executing API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
// 线程是否已经结束
@property (readonly, getter=isFinished) BOOL finished API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
// 线程是否已经调用cancel方法 (调用cancel后线程不会立即退出, 此时finished有可能为NO)
@property (readonly, getter=isCancelled) BOOL cancelled API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

#pragma mark - 类方法
// 当前线程 (类方法)
@property (class, readonly, strong) NSThread *currentThread;
// 是否主线程 (类方法)
@property (class, readonly) BOOL isMainThread API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0)); // reports whether current thread is main
// 获取主线程 (类方法)
@property (class, readonly, strong) NSThread *mainThread API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
// 是否多线程 (如果是通过非Cocoa的api开启的线程, 比如POSIX或者Multiprocessing Services APIs, 被认为不是多线程.)
+ (BOOL)isMultiThreaded;
// 线程休眠到aDate的时候 (在休眠期间run loop不处理事件)
+ (void)sleepUntilDate:(NSDate *)date;
// 休眠ti秒
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
// 强行停止线程 (应该避免调用此方法, 因为它不会使线程有机会清理在执行过程中分配的任何资源.)
+ (void)exit;
// 获取线程优先级 (0.0~1.0) (典型值是0.5, 但是由于优先级是由内核确定的, 因此不能保证此值实际上是多少)
+ (double)threadPriority;
// 设置线程优先级
+ (BOOL)setThreadPriority:(double)p;

#pragma mark - 对象方法
// 给线程发送取消信号, 最终何时取消由线程本身决定
- (void)cancel API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
// 开启线程
- (void)start API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
// 执行start方法后会自动调用main方法 (如果要继承NSThread, 可以重写main方法来执行新线程的主要部分)
- (void)main API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));	// thread body method

#pragma mark - 创建
// 创建新线程 (iOS 10+可用)
+ (void)detachNewThreadWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
// 创建新线程 (使用指定的选择器作为线程入口点)
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;
// 初始化NSThread对象
- (instancetype)init API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0)) NS_DESIGNATED_INITIALIZER;
// 初始化NSThread对象 (使用selector)
- (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
// 初始化NSThread对象 (使用block, iOS 10+可用)
- (instancetype)initWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

#pragma mark - 线程切换
// 切换到主线程 (在主线程调用SEL方法), wait: 是否阻塞当前线程
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array;
// 同上 (线程模式为kCFRunLoopCommonModes)
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
// 切换到指定线程 (在指定线程调用SEL方法)
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
// 同上 (线程模式为kCFRunLoopCommonModes)
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
// 在新的后台线程上调用SEL方法 (注意: 此方法创建新线程)
- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

示例

创建一个子线程, 在子线程中改变value值, 然后回到主线程打印该value值.

OC

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [NSThread detachNewThreadSelector:@selector(changeValue) toTarget:self withObject:nil];
}


- (void)changeValue {
    
    NSLog(@"%s thread:%@, value=%d", __func__, [NSThread currentThread], self.value);
    self.value = 10;
    // 调用主线程
    [self performSelectorOnMainThread:@selector(logValue) withObject:nil waitUntilDone:NO];
}


- (void)logValue {
    
    NSLog(@"%s thread:%@, value=%d", __func__, [NSThread currentThread], self.value);
}

-----------------------------------------------------------------------------------------------------
log:
-[ViewController changeValue] thread:<NSThread: 0x60000262b1c0>{number = 7, name = (null)}, value=0
-[ViewController logValue] thread:<NSThread: 0x60000266d0c0>{number = 1, name = main}, value=10

Swift

class KKThread: NSObject {
    
    var value: Int = 0
    

    @objc func startThread() {
        
        Thread.detachNewThreadSelector(#selector(changeValue), toTarget: self, with: nil)
    }
    
    
    @objc func changeValue() {
        
        print("\(#function), thread:\(Thread.current), value=\(self.value)")
        self.value = 5
        // 调用主线程
        self.performSelector(onMainThread: #selector(logValue), with: nil, waitUntilDone: false)
    }
    
    
    @objc func logValue() {
        
        print("\(#function), thread:\(Thread.current), value=\(self.value)")
    }
}

注: 关于OC中调用Swift请移步iOS开发之Swift篇(15)—— Swift与Objective-C混编

热门文章

暂无图片
编程学习 ·

7 模块与包

7 模块与包 Python中的模块和包一个py文件就是一个模块,py文件的文件名就是模块名。在 Python 里为了对模块分类管理,就需要划分不同的文件夹。多个有联系的模块可以将其放到同一个文件夹下,为了称呼方便,一般把 Python 里的一个代码文件夹称为一个包。7.1 导入模块导入模块…
暂无图片
编程学习 ·

ubuntu:beyond compare 4 This license key has been revoked 解决办法

错误如图所示:解决办法:(1)先用find命令找到bcompare所在位置:sudo find /home/ -name *bcompare(2)进入 /home/whf/.config,删除/bcomapre文件夹注意一般.config为隐藏文件,通过 ctrl+h 可以显示:(3)cd /usr/lib/beyondcompare/ (4)sudo sed -i "s/keexjEP3…
暂无图片
编程学习 ·

JavaScript-Promise的使用及详细解释

JavaScript-Promise的使用及详细解释案例使用多种方法实现以下案例第一种---setTimeout嵌套第二种---封装函数Promise详解小案例第三种---使用Promise来实现最开始的案例Promise---具体使用的案例第一版---点击按钮显示图片第二版---加载出第一张之后在加载其他,依次加载第三版…
暂无图片
编程学习 ·

leetcode-341-扁平化嵌套列表迭代器-java

题目及测试package pid341; /* 扁平化嵌套列表迭代器给你一个嵌套的整型列表。请你设计一个迭代器,使其能够遍历这个整型列表中的所有整数。列表中的每一项或者为一个整数,或者是另一个列表。其中列表的元素也可能是整数或是其他列表。示例 1:输入: [[1,1],2,[1,1]] 输出: […
暂无图片
编程学习 ·

7-9 1.2.5 双重回文数 (70分)

如果一个数从左往右读和从右往左读都是一样,那么这个数就叫做“回文数”.例如,12321 就是一个回文数,而 77778 就不是. 当然,回文数的首和尾都应是非零的,因此 0220 就不是回文数. 事实上,有一些数(如 21),在十进制时不是回文数,但在其它进制(如二进制时为 10101)时就是 回…
暂无图片
编程学习 ·

微信小程序--修改switch组件的大小

修改switch组件的大小 小程序中switch组件的大小往往和实际项目中的大小有些出入,但是发现文档中并没有修改大小的方法,但是可以根据自己的实际情况进行颜色设置。 直接上代码: <switch checked>正常开关</switch> <switch checked style="transform:sc…
暂无图片
编程学习 ·

SpringMVC框架的详细操作步骤和注解的用法

springMVC操作步骤: 第一步:导入jar(spring4个核心+日志+spring-web+spring-webmvc+spring-aop) 第二步:在web.xml中配置前端控制器(servlet),并读取springmvc的资源文件springmvc.xml<servlet><servlet-name>springDispatcherServlet</servlet-name><ser…
暂无图片
编程学习 ·

文件-复制-删除-移动

import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.InputStream; import java.io.PrintWriter; public class CopyFile { public CopyFile() { } /** * 新建目录 * @param folderPat…
暂无图片
编程学习 ·

postman引入文件实现参数化及中文乱码问题解决

1、首先,在postman中输入地址和参数,保证接口请求成功。可以在tests中添加断言2、将需要参数化的参数用变量表示,并将变量添加进全局变量中3、将需要参数化的参数写成CSV,TXT,JSON格式的文档。这里用的是csv格式的文件,其中name是变量名如果用txt格式的文件,多参数之间要用…
暂无图片
编程学习 ·

安装JDK

安装JDK 前提 要准备好jdk的包:jdk-8uxxx-linux-x64.tar.gz //JAVA 8 版本都可以 笔者这里使用的171 下载地址:Java SE 8 存档下载. 步骤 一、 解压jdk:tar -zxvf jdk-8u171-linux-x64.tar.gz二、 设置环境变量,编辑文件添加如下: vi /etc/profile export JAVA_HOME=/us…
暂无图片
编程学习 ·

jQuery 的实现原理

(function(window, undefined) {})(window); jQuery 利用 JS 函数作用域的特性,采用立即调用表达式包裹了自身,解决命名空间和变量污染问题 window.jQuery = window.$ = jQuery; 在闭包当中将 jQuery 和 $ 绑定到 window 上,从而将 jQuery 和 $ 暴露为全局变量
暂无图片
编程学习 ·

Query&Filtering与多字符串多字段查询

Query&Filtering与多字符串多字段查询Query Context & Filter Contxtbool查询bool查询语法如何解决结构化查询 - "包含而不是相等"的问题增加count字段,是用bool查询解决Filter Context - 不影响算分Query Context - 影响算分bool嵌套查询语句的结构,会对相…
暂无图片
编程学习 ·

Android-MPAndroidChart:RadarChart(雷达蜘蛛图)绘制圆点

目录思路实现思路来源于Homilier,感谢博主!效果是这样子的:思路从RadarChart类中我们可以看到init()方法中的内容,可以看出来自定义了绘制类。仅从字面我们就可以看出RadarChartRenderer是绘制雷达的,YAxisRendererRadarChart和XAxisRendererRadarChart是绘制x轴/y轴相关内…
暂无图片
编程学习 ·

10年开发码农带你理解MySQL——架构与概念&索引与优化

前言最早接触的MySQL是在三年前,那时候MySQL还是4.x版本,很多功能都不支持,比如,存储过程,视图,触发器,更别说分布式事务等复杂特性了。但从5.0(2005年10月)开始,MySQL渐渐步入企业级数据库的行列了;复制、集群、分区、分布式事务,这些企业级的特性,使得现在的MySQL…
暂无图片
编程学习 ·

Map和Set HashMap 二叉搜索树

1 搜索: 在大量的数据元素中找到某个特定的数据元素. 2 搜索的数据称为关键字(Key),和关键字对应的称为值(Value),所以模型会有两种: (1) 纯 key 模型,即我们使用 Set 要解决的事情,只需要判断关键字在不在集合中即可,没有关联的 value. (2) Key-Value 模型, 即我们 Map…
暂无图片
编程学习 ·

Vue或uni-app 使用外部.js文件定义全局变量和全局方法

定义一个xxx.js文件,名称可自行定义,例如此文件名为 helper.js,放在common文件夹下 ,内容如下:// 如果需要访问this,需要引入Vue实例,如果需要路由则需要引入路由,(需要使用到什么就引入什么) import Vue from vue // 字符串 var str = http://www.baidu.com// 对象 var o…
暂无图片
编程学习 ·

要哭了!一下午终于弄好了,pycharm和python的pyqt5安装

安装pyqt5和sip还有pyqt5-tools,我遇到了所有能遇到的问题,诸如配置问题,没安装sip,缺少vcruntime140_1.dll文件,还有 pyqt5打开designer提示This application failed to start because no Qt platform plugin could be initialized问题,搞了一下午,真的要哭了,慢慢就解…
暂无图片
编程学习 ·

fluter的环境搭配及android studio开发

fluter的环境搭配及android studio开发step1系统要求step2获取Flutter SDKstep3更新环境变量1、镜像环境设置1、在用户变量2、系统变量step4 Android设置1、安装Android Studio2、在命令终端terminal中配置flutter相关3、设置您的Android设备 step1系统要求 开发环境必须满足以…