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混编

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

上一篇下一篇

猜你喜欢

热点阅读