zoukankan      html  css  js  c++  java
  • 多线程

    1.进程

    系统中一个正在运行的应用程序就是一个进程.

    比如mac下,正在运行的程序,在活动监视器中表现为一个个进程

    问?只有正在运行的应用程序才能称之为一个进程把??

    2.多线程

    程序最终是由CPU执行的,粗略的说,一个CPU单位时间只能执行一个任务,也就是不能同时刷新UI,又执行下载操作.任务都是在线程中执行的,如果将刷新UI放在一个线程中执行,将下载等耗时操作放在另一线程中执行,那么问题就能够得到解决.然而在单个CPU的硬件条件下,这种同时执行多个任务仍然只是一种幻象,因为其实这只是CPU高速在多个线程之间切换,并不是真正意义上的多个线程同时执行任务.随着硬件的发展,多核的实现,多线程才不在是速度导致的幻象.

    粗略的说是这样,我还有许多困惑,比如如何让CPU在多个线程之间切换,线程本质是什么?亦即,代码究竟如何同硬件交互,产生神奇的效果的,但是这不是这里的重点,先略过.

    2.1主线程.子线程

    程序一旦启动就会创建一条主线程.主线程以外的线程都可以称为子线程或者后台线程.

    如图,我在viewDidLoad方法中打了断点,主线程程序一经启动由系统创建,并且默认是串行的(serial)

    主线程通常又称为UI线程.主要用于处理和UI相关的操作,如显示界面,相应触摸,点击等事件.

    子线程用于处理耗时操作.如下载等....

    3.pthread

    C语言实现多线程的技术.

    用法:

      pthread_create(pthread_t *restrict, const pthread_attr_t *restrict, void *(*)(void *), void *restrict)
         pthread_t *restrict  pthread类型数据的地址
         const pthread_attr_t *restrict 通常传NULL
         void *(*)(void *)  函数的指针,函数名即函数的地址,因而不需要取地址,和数组类似.
         void *restrict 函数的参数.

    使用上面的函数即可创建一个子线程.

    例;


    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { pthread_t pthread = NULL; //创建一个子线程 pthread_create(&pthread, NULL, pthreadOpertion, c); }
    //模拟耗时操作
    void * pthreadOpertion(void *str) { for (int i = 0; i < 10000; i ++) { NSLog(@"%d",i); } NSLog(@"%s",str); return str; }

    4.NSThread

    有三种创建子线程的方式

    >1.类方法

     [NSThread detachNewThreadSelector:@selector(longTimeOperationWithObject:) toTarget:self withObject:@"类方法"];

    >2.对象方法

        NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(longTimeOperationWithObject:) object:@"对象方法"];
        [thread start];//将创建的线程加入可调度线程池.CPU才会读取到子线程并执行相应代码.//其他两种由系统将线程加入可调度线程池.

    >3.NSObject分类方法

     [self performSelectorInBackground:@selector(longTimeOperationWithObject:) withObject:@"NSOject的分类方法"];
    //模拟的耗时操作
    - (void)longTimeOperationWithObject:(id)obj
    {
    
        NSLog(@"%@----%@",[NSThread currentThread],obj);
        for (NSInteger i = 0; i < 10000; i ++) {
            NSLog(@"%ld",i);
        }
    }

    常用的方法和属性

    + (NSThread *)currentThread;//获取当前线程
    + (BOOL)isMultiThreaded;//是否是子线程
    + (void)sleepUntilDate:(NSDate *)date;//让线程进入休眠状态
    + (void)sleepForTimeInterval:(NSTimeInterval)ti;//同上
    + (void)exit;//结束当前线程
    + (double)threadPriority;//设置线程优先级.只是就概率意义而言.范围在0.0-1.0之间,1.0,优先级最高,仅仅意味着执行该线程的可能性高一些,具体分配取决于CPU
    @property NSUInteger stackSize NS_AVAILABLE(10_5, 2_0);//线程开销.IOS/OS X的主线程目前默认都是512KB
    @property (readonly) BOOL isMainThread NS_AVAILABLE(10_5, 2_0);//是否是主线程
    - (void)cancel NS_AVAILABLE(10_5, 2_0);//给线程打上取消标记,通过"@property (readonly, getter=isCancelled) BOOL cancelled NS_AVAILABLE(10_5, 2_0);"判断线程状态,如果是取消状态,会终止当前线程

    分类方法
    - (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
    //上面两个方法都是:在主线程执行aSelector方法,方法的参数为arg,waitUntilDone:(BOOL)wait:是否等到该方法执行结束往下执行.传入YES,需要等到aSelector方法执行完毕,才会继续往下执行,为NO,则不必等aSelector方法执行完即可向下执行,见下面例1
    - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array NS_AVAILABLE(10_5, 2_0);
    - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0);
        // equivalent to the first method with kCFRunLoopCommonModes
    //上面两个方法都是:在指定的线程中执行任务.
    - (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg NS_AVAILABLE(10_5, 2_0);//在子线程中执行任务.

    例1;

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        [self test];
    
    }
    
    - (void)test
    {
        [NSThread detachNewThreadSelector:@selector(test2) toTarget:self withObject:nil];
    
    }
    
    - (void)test2
    {
        for (NSInteger i = 0; i < 10; i ++) {
            NSLog(@"%ld",i);
        }
    
        [self performSelectorOnMainThread:@selector(test3) withObject:self waitUntilDone:YES];
    
        //如果为YES,表示需要等到test3执行完才继续往后执行
        //如果为NO,表示不需要等到test3执行完就可以继续往后执行/
    
        NSLog(@"test2");
    
    }
    
    
    - (void)test3
    {
    
        for (NSInteger i = 0; i < 10; i ++) {
            NSLog(@"%ld",i);
        }
    
        NSLog(@"test3");
    }
     [self performSelectorOnMainThread:@selector(test3) withObject:self waitUntilDone:YES];为YES输出结果:
    2016-03-13 00:15:51.381 NSThread分类方法[2994:123374] 0
    2016-03-13 00:15:51.381 NSThread分类方法[2994:123374] 1
    2016-03-13 00:15:51.381 NSThread分类方法[2994:123374] 2
    2016-03-13 00:15:51.381 NSThread分类方法[2994:123374] 3
    2016-03-13 00:15:51.382 NSThread分类方法[2994:123374] 4
    2016-03-13 00:15:51.415 NSThread分类方法[2994:123272] 0
    2016-03-13 00:15:51.416 NSThread分类方法[2994:123272] 1
    2016-03-13 00:15:51.416 NSThread分类方法[2994:123272] 2
    2016-03-13 00:15:51.416 NSThread分类方法[2994:123272] 3
    2016-03-13 00:15:51.416 NSThread分类方法[2994:123272] 4
    2016-03-13 00:15:51.416 NSThread分类方法[2994:123272] test3
    2016-03-13 00:15:51.419 NSThread分类方法[2994:123374] test2

    为NO输出结果

    2016-03-13 00:16:26.380 NSThread分类方法[3015:124168] 0
    2016-03-13 00:16:26.382 NSThread分类方法[3015:124168] 1
    2016-03-13 00:16:26.382 NSThread分类方法[3015:124168] 2
    2016-03-13 00:16:26.383 NSThread分类方法[3015:124168] 3
    2016-03-13 00:16:26.383 NSThread分类方法[3015:124168] 4
    2016-03-13 00:16:26.383 NSThread分类方法[3015:124168] test2
    2016-03-13 00:16:26.416 NSThread分类方法[3015:124065] 0
    2016-03-13 00:16:26.416 NSThread分类方法[3015:124065] 1
    2016-03-13 00:16:26.416 NSThread分类方法[3015:124065] 2
    2016-03-13 00:16:26.416 NSThread分类方法[3015:124065] 3
    2016-03-13 00:16:26.416 NSThread分类方法[3015:124065] 4
    2016-03-13 00:16:26.417 NSThread分类方法[3015:124065] test3

    线程的生命周期

    创建----就绪-----运行-----死亡.在运行和死亡之间穿插阻塞(睡眠)

    死亡又分为三种;

    自然死.任务执行完毕

    自杀:[NSThread exit];

    他杀:[NSThread cancel],被打上取消标记,

  • 相关阅读:
    阿里云主机和RDS使用心得
    iOS_2_button控制物体形变
    js 继承概述
    Android 代码混淆
    “...”是字段,但此处被当作类型来使用
    Mali GPU OpenGL ES 应用性能优化--測试+定位+优化流程
    uva 213
    XML基础以及用DOM4j读取数据
    【Hibernate】Hibernate3.x独立执行时的Failed to load class &quot;org.slf4j.impl.StaticLoggerBinder&quot;错误
    《Pro Android Graphics》读书笔记之第六节
  • 原文地址:https://www.cnblogs.com/yufang/p/5271050.html
Copyright © 2011-2022 走看看