1.多线程之NSThread

基本概念:

1.进程:mac系统中运行的每一个应用程序就是一个进程,进程之间是独立的,有自己的内存区域,可在活动管理器中查看

2.线程:每个进程最少有一条线程,可有多条线程,任务都在线程中执行

3.线程串行:如果在一个线程中执行多个任务,只能排队顺序执行,一个完了执行下一个

4.线程并行(多线程):一个进程开启N条线程,每条线程执行不同任务,可提高任务效率

5.cpu处理:同一时间,cpu只能处理一条线程,处理多条线程只是在不同线程间快速切换处理,只因为足够快速,给人的感觉就像同时处理;线程开启的越多,耗费cpu资源越多,线程开启过多,导致cpu利用率过高,执行效率降低,通俗表现就是卡、慢

6.优缺点:iOS下创建线程的开销包括:内核数据结构(大约1KB)、栈空间(子线程512k,主线程1M,也可以使用-setStackSize:设置,但必须是4K的倍数,最小为16K),创建线程大约为90ms

1⃣️优点是执行效率高,提高资源利用率;2⃣️缺点是开启过多时,会降低性能,开销变大,业务逻辑也会复杂,比如线程间通信

7.每个进程会默认启动一条线程,称为主线程或UI线程,主要用来显示刷新UI及处理UI事件,如果主线程操作比较耗时,会造成主线程卡顿,耗时操作建议放置于子线程进行,

8.多线程常用技术:NSThread、GCD、NSOperation

………………………………………………………………………………………………………………………………………………………………

NSThread方案:

一个NSThread对象就代表一条线程

1. 创建、启动线程

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];

[thread start];

1.1 主线程相关用法

+ (NSThread *)mainThread; // 获得主线程

- (BOOL)isMainThread; // 是否为主线程

+ (BOOL)isMainThread; // 是否为主线程

1.2 获得当前线程

NSThread *current = [NSThread currentThread];

1.3 线程的名字

- (void)setName:(NSString *)n;

- (NSString *)name;

2. 创建子线程(快速创建新线程)

[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil]; //Object:传参数进去

3. 隐式创建子线程

[self performSelectorInBackground:@selector(run) withObject:nil]; //Object:传参数进去

上述2种创建线程方式简单快捷,无法对线程进行更详细的设置名字、优先级等

4. 线程状态:

1.多线程之NSThread_第1张图片

5.控制线程状态

5.1启动线程

- (void)start;  //进入就绪状态 》运行状态,任务执行完毕,进入死亡状态

5.2阻塞线程

+ (void)sleepUntilDate:(NSDate *)date; //[NSDate dateWithTimeIntervalSinceNow:2]从现在开始阻塞2秒

+ (void)sleepForTimeInterval:(NSTimeInterval)ti;

5.3强制停止线程

+ (void)exit;//线程停止,就不能再次开启

6.线程安全问题

一块资源被多条线程访问,可能会引起数据错乱和数据安全问题

6.1 安全解决方案 -- 互斥锁 --(线程同步)

格式:@synchronized(锁对象){需要锁定的代码}

加锁后,锁定的代码只会被某一条线程所访问。锁对象需要是一个全局对象,多个锁对象无效。一般使用self就行。比较消耗资源

7.原子和非原子属性

atomic:原子属性,为setter方法加锁,系统默认,线程安全,耗费资源

nonatomia:非原子属性,不为setter方法加锁,非线程安全,适合移动设备,默认使用

8.线程间通信

以下载图片为例,图片在子线程下载,完成后需要在主线程加载刷新UI,这就是简单的线程间通信

8.1线程间通信常用方法

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;

- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;

举个栗子:

// 回到主线程,显示图片

[self performSelectorOnMainThread:@selector(showImage:) withObject:image waitUntilDone:YES];

- (void)showImage:(UIImage *)image

{

    self.imageView.image = image;

}

等价

[self.imageView performSelector:@selector(setImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:NO];

//意思是在主线程中调用setter方法,将数据设置给imageview,waitUntilDone:NO--设置为NO意味着调用完setter方法,就继续执行下面的代码,不等待,YES则是完成后,才继续执行下面的代码

9.计算图片下载使用时长

9.1 使用当前日期时间

NSDate *begin = [NSDate date];

// 根据图片的网络路径去下载图片数据

NSData *data = [NSData dataWithContentsOfURL:url];

NSDate *end = [NSDate date];

NSLog(@"%f", [end timeIntervalSinceDate:begin]);

9.2 使用自1970以来的秒数计算

CFTimeInterval begin = CFAbsoluteTimeGetCurrent();

// 根据图片的网络路径去下载图片数据

NSData *data = [NSData dataWithContentsOfURL:url];

CFTimeInterval end = CFAbsoluteTimeGetCurrent();

NSLog(@"%f", end - begin);


你可能感兴趣的:(1.多线程之NSThread)