NSThread

作者: edison0428 | 来源:发表于2018-07-27 23:33 被阅读10次

    NSThread 使用更加面向对象,是OC,简单易用,可直接操作线程对象 ,线程的生命周期归属于程序员管理

    在iOS领域中真正的多线程技术就是pthreadNSThread,那么GCD呢,GCD不能直接操作线程,是封装好的并发技术,它是操作队列,和线程不管,特别安全,NSOperation也是一样的,所以多线程技术只有两个pthreadNSThread 苹果官方并不鼓励开发者使用多线程技术,而是推荐并发技术,这也是为什么苹果主推GCD`的原因

    关于创建线程
    1.
    - (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument 
    
    2.
    - (instancetype)initWithBlock:(void (^)(void))block 
    
    3.
    + (void)detachNewThreadWithBlock:(void (^)(void))block 
    
    4.
    + (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;
    
    
    5.
    NSThread * t=[[NSThread allloc] init]
    [t start];
    如上运行不起来
    [[NSThread allloc] init] 这个只适合NSThread子类也就是自定义的NSThread
    

    前两种方法是对象方法,创建完成之后需要start,而有两种方法是类方法detach表示分派,就是直接运行新的线程了

    还有几个方法,不在NSThread的头文件里
    它们是NSObject的分类
    所以它很方便,意味着所有的基础的NSObject都可以调用这个如下方法,不需要创建NSThread对象

    - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array;
    - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
        // equivalent to the first method with kCFRunLoopCommonModes
    
    - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array 
    - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait 
        // equivalent to the first method with kCFRunLoopCommonModes
    - (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg 
    

    代码出来
    如上的方法,aSelector方法会不会执行,要看onThread的线程是否还在,如果线程已经被执行完了那么aSelector方法就不会被调用

    1.
    [self performSelectorInBackground:@selector(test) withObject:nil];
    test方法就是在后台(子线程)里执行
    
    
    线程的状态

    先po出一张图


    image.png

    线程创建了之后,存放在内存中的可调度线程池中,这个可调度线程池我们好像是不能操作的,是有CPU进行调度的

    当我们Start方法的时候,线程会被放入可调度线程池中,此时的状态是Runnable就绪状态,当CPU调度这个线程的时候,那么它的状态是运行状态,当CPU调度其他线程的时候,那么它的状态又是Runnable就绪状态,当线程在运行状态的时候我们通过sleep方法或者等待同步锁(线程被锁在外面了)让线程称为阻塞Blocked的状态,当线程在阻塞状态的时候,线程不在可调度线程池,当前sleep时间到了或者锁开了,此线程又回到了可调度线程池称为Runnable就绪状态等待被调度,当任务执行完毕了或者强制退出或者出现异常,此时线程的状态是死亡的状态,线程会被从可调度线程池拿出来然后再被干掉

    线程的状态的可控性

    如上图所示
    可控的状态,只有StartRunnable就绪状态,阻塞Blocked的状态,死亡的状态
    设计到CPU怎么调度的都不是我们可控的

    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        
        //创建线程
        NSThread * thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadTest) object:nil];
        
        //线程就绪状态  (cpu 翻牌)
        [thread start];
    }
    
    -(void)threadTest{
        //阻塞 让线程睡会儿
        //方法:sleep 是类方法  会直接休眠当前线程  当前线程是t线程
        
        [NSThread sleepForTimeInterval:2];
        
        for (int i = 0; i<20; i++) {
            
            NSLog(@"%@  ->%d",[NSThread currentThread],i);
            
            if (i==10) {
                //当线程满足一定条件的时候,可以强行终止线程
                //exit 是类方法 终止的是当前的线程
                /*
                 一旦强行终止线程 后续的所有代码将不会被执行
                 如果线程是主线程 那么主线程是没法被杀掉的,但是会让主线程阻塞,但是阻塞之后,就没法重新开启,所以相当于杀死一样的效果,只不过app还活着
                 
                 所以注意了:在终止线程之前,如果我们分配的对象,我们应该再exit之前释放他们
                 */
                [NSThread exit];
            }
        }
    }
    
    NSThread的属性
    • name:线程名,没什么大用,不过在捕捉奔溃时候 能看到是在那条线程奔溃的

    • threadPriority :优先级级别 0-1 级别越高,只是保证CPU调度的可能性会高一点,在多线程的开发中,不建议修改优先级
      在多线程的开发中,不要相信一次的运行结果

    多线程的安全隐患(资源共享)

    一个资源可能同时会被多个线程共享,也就是多个线程可能会访问同一个资源,比如多个线程访问同一个对象,同一个变量,同一个文件,当多个线程访问同一个资源时,很容易引发数据错乱和数据安全问题

    解决资源共享的问题

    • 互斥锁
      互斥锁--保证锁内的代码,同一时间只有一条线程可执行
      互斥锁的范围应该尽量小,范围大了,效率就差
    //参数:self  或者任何oc对象都可以
    @synchronized(self){
            
            //加锁的内容
            
        }
    
    //
    NSObject * lock = [NSObject new];
    @synchronized(lock){
            
            //加锁的内容
            
        }
    这就是锁不住,不是说了任何oc对象都可以嘛,因为lock是局部变量,每次进来都是重新创建,归当前线程单独拥有,除非用全部变量,但是一般用self
    

    相关文章

      网友评论

          本文标题:NSThread

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