美文网首页
iOS开发之多线程(2)—— Thread

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

作者: 看影成痴 | 来源:发表于2020-07-01 16:19 被阅读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

    相关文章

      网友评论

          本文标题:iOS开发之多线程(2)—— Thread

          本文链接:https://www.haomeiwen.com/subject/ebchqktx.html