您的位置:首页 > 移动开发 > IOS开发

iOS开发多线程篇—多线程简单介绍

2016-01-04 12:13 441 查看

基本概念

同步:在当前线程中执行任务,不具备开启新线程的能力

异步:在新的线程中执行任务,具备开启新线程的能力

串行:一个任务执行完毕后,再执行下一个任务

并行:多个任务同时执行

并发:多个事件在同一个时间间隔内发生,但任一时刻只有一个程序运行

线程同步:多条线程安顺序执行

阻塞(blocking):表示需要等待A事件完成后才能完成B事件,称作A会阻塞B,通俗来讲就是强制等待的意思

死锁(deadlock):表示由于某些互相阻塞,也就是互相的强制等待,形成了闭环,导致大家永远互相阻塞下去了,Always and Forever,也就是死锁。

一、进程和线程

1.什么是进程

进程是指在系统中正在运行的一个应用程序,每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内。

比如:

打开QQ、Xcode,系统就会分别启动2个进程




2.什么是线程

线程是进程的基本执行单元,一个进程(程序)的所有任务都在线程中执行,1个进程要想执行任务,必须得有线程(每1个进程至少要有1条线程)。

比如:

使用酷狗播放音乐、使用迅雷下载电影,都需要在线程中执行.




3.线程是串行

1个线程中任务的执行是串行的,如果要在1个线程中执行多个任务,那么只能一个一个地按顺序执行这些任务。也就是说,在同一时间内,1个线程只能执行1个任务

比如:

在1个线程中下载3个文件(分别是文件A、文件B、文件C)




二、多线程

1.什么是多线程

1个进程中可以开启多条线程,每条线程可以并行(同时)执行不同的任务,多线程技术可以提高程序的执行效率。

比如:

同时开启3条线程分别下载3个文件(分别是文件A、文件B、文件C)




2.多线程的原理

同一时间,CPU只能处理1条线程,只有1条线程在工作(执行),多线程并发(同时)执行,其实是CPU快速地在多条线程之间调度(切换),如果CPU调度线程的时间足够快,就造成了多线程并发执行的假象。

思考:如果线程非常非常多,会发生什么情况?

CPU会在N多线程之间调度,CPU会累死,消耗大量的CPU资源,每条线程被调度执行的频次会降低(线程的执行效率降低)。


3.多线程的优缺点

多线程的优点:

能适当提高程序的执行效率

能适当提高资源利用率(CPU、内存利用率)

多线程的缺点:

开启线程需要占用一定的内存空间(默认情况下,主线程占用1M,子线程占用512KB)。如果开启大量的线程,会占用大量的内存空间,降低程序的性能,线程越多,CPU在调度线程上的开销就越大,程序设计更加复杂:比如线程之间的通信、多线程的数据共享

4.多线程在iOS开发中的应用

主线程:

一个iOS程序运行后,默认会开启1条线程,称为“主线程”或“UI线程”。


主线程的主要作用:

1.显示\刷新UI界面
2.处理UI事件(比如点击事件、滚动事件、拖拽事件等)


注意:

别将比较耗时的操作放到主线程中。耗时操作会卡住主线程,严重影响UI的流畅度,给用户一种“卡”的坏体验。


iOS开发多线程篇—线程安全

一、多线程的安全隐患

资源共享,1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源。

比如:

多个线程访问同一个对象、同一个变量、同一个文件。当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题




二、安全隐患分析

[b]1 产生问题:[/b]



[b]2 解决问题:[/b]



三、如何解决

1.使用互斥锁

互斥锁的使用前提:

多条线程抢夺同一块资源 。
互斥锁,就是使用了线程同步技术。
线程同步既是多条线程按顺序地执行任务。


@synchronized(锁对象) { // 需要锁定的代码  }
例如:
//只能一把锁
@synchronized(self) {
NSLog(@"示例代码");
}


注意:锁定1份代码只用1把锁,用多把锁是无效的

2 互斥锁的优缺点

优点:能有效防止因多线程抢夺资源造成的数据安全问题

缺点:需要消耗大量的CPU资源

3 死锁产生的四个条件

互斥条件:一个资源每次只能被一个进程使用

请求和保持请求:一个进程因请求资源而阻塞时,对已获得的资源保持不放

不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺

循环等待条件:若干进程之间形成一种头尾相接的循环等待的资源关系

四:原子和非原子属性

OC在定义属性时有nonatomic和atomic两种选择

atomic:原子属性,为setter方法加锁(默认就是atomic)。线程安全,需要消耗大量的资源

nonatomic:非原子属性,不会为setter方法加锁。非线程安全,适合内存小的移动设备。

//atomic加锁原理
@property (assign, atomic) int age;

- (void)setAge:(int)age
{

@synchronized(self) {
_age = age;
}
}


五 iOS开发的建议

所有属性都声明为nonatomic

尽量避免多线程抢夺同一块资源

尽量将加锁、资源抢夺的业务逻辑交给服务器端处理,减小移动客户端的压力

iOS开发多线程篇—线程间通信

1 创建线程

(1)手动创建线程,可以进行详细设置

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"可以是run的参数,也可以为nil"];
[thread setName:@"线程名字"];
//线程的调度优先级:调度优先级的取值范围是0.0 ~ 1.0,默认0.5,值越大,优先级越高
[thread setThreadPriority:0.5];
//是否是主线程
[thread isMainThread];
//手动开始
[thread start];
//获得主线程
NSThread *mainThread = [NSThread mainThread];
//获取当前线程
NSThread *currentThread = [NSThread currentThread];
[self performSelectorInBackground:@selector(run:) withObject:@"1"];


(2)创建线程后自动启动线程

[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];


(3)隐式创建并启动线程

[self performSelectorInBackground:@selector(run) withObject:nil];


上述2种创建线程方式的优缺点

优点:简单快捷

缺点:无法对线程进行更详细的设置

2 线程通信

1 一个线程传递数据给另一个线程

2 在一个线程中执行完特定任务后,转到另一个线程继续执行任务


2.1
NSObject
中的一些方法:

在应用程序主线程中做事情:

performSelectorOnMainThread:withObject:waitUntilDone:

performSelectorOnMainThread:withObject:waitUntilDone:modes:

在指定线程中做事情:

performSelector:onThread:withObject:waitUntilDone:

performSelector:onThread:withObject:waitUntilDone:modes:

waitUntilDone参数是个bool值,如果设置为NO,相当于异步执行,当前函数执行完,立即执行后面的语句。如果设置为YES,相当于同步执行,当前线程要等待Selector中的函数执行完后再执行。

在当前线程中做事情:

performSelector:withObject:afterDelay:

performSelector:withObject:afterDelay:inModes:

取消发送给当前线程的某个消息

cancelPreviousPerformRequestsWithTarget:

cancelPreviousPerformRequestsWithTarget:selector:object:

2 .2
GCD
一个线程传递数据给另一个线程

dispatch_queue_t concurrentQueue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue2, ^{
__block UIImage *image2 = nil;
NSLog(@"2");
NSLog(@"%@",[NSThread currentThread]);
dispatch_sync(concurrentQueue2, ^{
/* Download the image here */
NSLog(@"3");
NSLog(@"%@",[NSThread currentThread]);
});
dispatch_sync(dispatch_get_main_queue(), ^{
/* Show the image to the user here on the main queue*/
NSLog(@"4");
NSLog(@"%@",[NSThread currentThread]);
});
});


iOS进程间通信之CFMessagePort

原文:

1.iOS开发多线程篇—多线程简单介绍
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: