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

来源:互联网 发布:安卓手机微信数据恢复 编辑:程序博客网 时间:2024/06/06 05:48

基本概念

  • 同步:在当前线程中执行任务,不具备开启新线程的能力
  • 异步:在新的线程中执行任务,具备开启新线程的能力
  • 串行:一个任务执行完毕后,再执行下一个任务
  • 并行:多个任务同时执行
  • 并发:多个事件在同一个时间间隔内发生,但任一时刻只有一个程序运行
  • 线程同步:多条线程安顺序执行

一、进程和线程

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块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源。

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

这里写图片描述

二、安全隐患分析

1 产生问题:

这里写图片描述

2 解决问题:

这里写图片描述

三、如何解决

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开发多线程篇—多线程简单介绍

0 0
原创粉丝点击