多线程

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],被打上取消标记,

 

posted @ 2016-03-13 00:28  Matrix_Neo  阅读(171)  评论(0编辑  收藏  举报