iOS开发之多线程(2)—— Thread
2020-07-01 本文已影响0人
看影成痴
文集
iOS开发之多线程(1)—— 概述
iOS开发之多线程(2)—— Thread
iOS开发之多线程(3)—— GCD
iOS开发之多线程(4)—— Operation
iOS开发之多线程(5)—— Pthreads
iOS开发之多线程(6)—— 线程安全与各种锁
目录
版本
简介
方法属性
示例
版本
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混编