Multithreading for iOS development (2)-Thread

Collected Works

Multithreading for iOS development (1)
-Overview of multithreading for iOS development (2)-Multithreading for Thread
iOS development (3)-Multithreading for GCD
iOS development (4)
-Operation Multithreading for iOS development ( 5)-Multithreading of Pthreads
iOS development (6)-Thread safety and various locks

version

Xcode 11.5
Swift 5.2.2

Introduction

A Thread is a thread.

Method attributes

Attribute method in OC (Swift method name is similar):

#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));

Example

Create a child thread, change the value in the child thread, and then return to the main thread to print the 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)")
    }
}

Note: Regarding calling Swift in OC, please move to Swift of iOS Development (15)-Mixed Swift and Objective-C

demo
https://github.com/LittleLittleKang/KKThreadsDemo

Guess you like

Origin blog.csdn.net/u012078168/article/details/107066632