最近在面试,重新温习了一遍多线程,希望加深一遍对于多线程的理解。

1、什么是进程?

1).要了解线程我们必须先了解进程,通俗来讲进程就是在系统中运行的一个应用程序。

2).每个线程之间是独立存在的,分别运行在其专用的且受保护的内存空间中。

3).比如打开QQ或Xcode系统会分别开启两个进程 如图:

iOS-多线程介绍

4)、我们可以通过"活动监视器"查看Mac系统中所开启的进程。

2、什么是线程?

1).一个进程要想执行任务必须得有线程,即一个进程至少要有一个线程。

2).线程是进程的基本执行单元,一个进程(程序)的所有任务都是在线程中执行的。

3).比如使用酷狗播放音乐、使用迅雷下载电影都需要在线程中运行 如图:

iOS-多线程介绍

3、什么是线程的串行?

1).一个线程中任务是串行执行的(顺序执行)的,也就是说一个线程同一时间内只能执行一个任务。

2).串行执行图解,比如一个线程下载3个文件(文件A、B、C)

iOS-多线程介绍

4、什么是多线程?

1).一个进程中可以开启多个线程,每个线程可以并发(同时)执行不同的任务。

2).类似关系列举:进程---->车间;线程---->车间工人

3).多线程图解,比如同时开启3个线程分别下载3个文件(文件A、B、C

iOS-多线程介绍

 

5、多线程原理

1).同一时间CPU只能执行一个线程,只有一个线程在工作(执行)。

2).多线程并发(同时)执行,其实是CPU快速的在多个线程之间调度(切换)。

3).如果CPU调度线程的速度够快,就会造成多线程并发执行的假象。

4).多线程的缺点:

   1、每个线程都会占用一定的内存空间(默认情况下:主线程占用1MB,子线程占用512KB),

        如果开启线程过多会占用大量的内存空间因而造成程序性能降低。

   2、线程越多CPU调度线程上的开销就越大(类似工厂工人越多,工厂开销也越大)。

   3、使程序设计更复杂:比如多线程的数据通信,多线程之间的数据共享。

5).多线程的优点:

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

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

6、什么是主线程?

 1).一个iOS程序开启后默认会开启一个线程,这个线程被称为"主线程"或"UI线程"。

 2).主线程的主要作用:

    1、显示/刷新UI界面

    2、处理UI事件(比如点击事件、滚动事件、拖拽事件等)

 3).主线程注意点:

    1、别将耗时的操作放在主线程中,耗时操作放在主线程中会造成程序卡顿的问题。

7、耗时操作Demo演示   

1)、直接在主线程中运行的Demo

 1 -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
 2     //获取当前执行方法和当前线程
 3     //number==1 主线程
 4     //number!=1 其他线程、子线程、次线程
 5     NSLog(@"%s----%@",__func__,[NSThread currentThread]);
 6     
 7     //直接在主线程中运行 造成UI操作卡顿
 8     [self longTimeOperation];
 9 }
10 
11 #pragma mark-耗时操作
12 -(void)longTimeOperation{
13     for (int i=0; i<20000; i++) {
14         NSLog(@"%d",i);
15     }
16 }
View Code

2)、在子线程中运行的Demo

 1 -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
 2     //获取当前执行方法和当前线程
 3     //number==1 主线程
 4     //number!=1 其他线程、子线程、次线程
 5     NSLog(@"%s----%@",__func__,[NSThread currentThread]);
 6     
 7     //将耗时操作放在子线程中执行,不影响UI的操作
 8     [self performSelectorInBackground:@selector(longTimeOperation) withObject:nil];
 9 }
10 
11 #pragma mark-耗时操作
12 -(void)longTimeOperation{
13     for (int i=0; i<20000; i++) {
14         NSLog(@"%d",i);
15     }
16 }
View Code

8、iOS中多线程的实现方案

技术方案 简介 语言 线程生命周期 使用频率
pthread
  • 一套通用的多线程API
  • 适用于Unix\Linux\Windows等系统
  • 跨平台可移植
  • 使用难度大
C 程序员管理 几乎不用
NSThread
  • 使用更加面向对象
  • 简单易用直接操作线程对象
OC 程序员管理 偶尔使用
GCD
  • 旨在替换NSThread等线程技术
  • 充分利用设备的多核
C 自动管理 经常使用
NSOperation
  • 基于GCD(底层是GCD)
  • 比GCD多了一些更简单实用的功能
  • 使用更加面向对象
OC 自动管理 经常使用

9、pthread 的使用 

 1 #import <pthread.h>
 2 -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
 3     [self test];
 4 }
 5 
 6 //使用pthread创建线程
 7 -(void)test{
 8     //声明一个线程变量
 9     pthread_t threadID;
10     
11     /*
12       参数:
13        1、要开的线程的变量
14        2、线程的属性
15        3、要在这个子线程中执行的函数(任务)
16        4、这个函数(任务)需要传递的参数
17      */
18     //pthread_create(pthread_t *restrict, const pthread_attr_t *restrict, void *(*)(void *), void *restrict);
19     
20     id str=@"hello";
21     //id 需要转成void * 需要使用__bridge进行桥连
22     //1、这里只是临时把str对象转成void *在这里临时使用,不改变这个对象的所有权
23     //2、把对象所有权交出去,在这个函数把str转成void *
24     //如果使用MRC 这里不需要使用桥连可以直接使用这个参数
25     //ARC自动内存管理,本质是编译器特性,是在程序编译的时候,编译器在适合的地方帮我们添加retain、release、autorelease
26     pthread_create(&threadID, NULL, run, (__bridge void*)str);
27 }
28 
29 #pragma mark-耗时操作
30 void *run(void *prama){
31      //void * 相当于OC里面的id
32     //__bridge 桥连操作
33     NSString *str=(__bridge NSString*)prama;
34     for (int i=0; i<20000; i++) {
35         NSLog(@"%d----%@----%@",i,[NSThread currentThread],str);
36 
37     }
38     return NULL;
39 }
View Code

相关文章: