1、什么是进程?

  进程是指在系统中正在运行的一个应用程序。比如同时打开QQ、Xcode,系统就会分别启动2个进程。截图

  

2、什么是线程?

  1)、一个进程要想执行任务,必须得有线程(每一个进程至少要有一条线程)

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

  3)、一个线程中任务的执行是串行的。即如果要在1个线程中执行多个任务,那么只能一个一个的按顺序执行这些任务

3、什么是多线程?

  1)、一个线程中可以开启多条线程,每条线程可以并行执行不同的任务。比如同时开启三条线程分别下载3个文件

  2)、同一时间,CPU只能处理一条线程,只有一条线程在工作(执行)

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

  4)、如果cpu调度线程的时间足够快,就造成了多线程并发执行的假象

  5)、如果线程非常非常多,那么会发生什么情况呢?

    可能导致cpu在N条线程之间调度,消耗大量的cpu资源,进而导致每条线程被调度执行的频次会降低(线程的执行效率降低)

  6)、多线程的优点:能适当提高程序的执行效率;能适当提高资源利用率(cpu、内存利用率)

  7)、多线程的缺点:

    开启线程需要占用一定的内存空间(默认情况下,主线程占用1M,子线程占用512KB),如果开启大量的线程,会占用大量的内存空间,降低程序的性能;

    线程越多,cpu在调度线程上的开销就越大;

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

4、什么是主线程

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

  2)、主线程的作用:

    显示/刷新UI界面;

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

  3)、主线程的使用注意:

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

    所以一般将耗时操作放在子线程(后台线程、非主线程)

5、ios中多线程的实现方案:

  

6、NSThread

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

  2)创建、启动线程:

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

    [thread start];

  3)、主线程相关用法:

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

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

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

  4)、获取当前线程: NSThread *current = [NSThread currentThread];

  5)、线程的调度优先级

    + (double)threadPriority;

    + (BOOL)setThreadPriority:(double)p;

    - (double)threadPriority;

    - (BOOL)setThreadPriority:(double)p;

    调度优先级的取值范围是0.0 ~ 1.0, 默认是0.5, 值越大,优先级越高

  6)、线程的名字:- (void)setName: (NSString *)n;   - (NSString *)name;

  7)、另外一种创建线程方法:创建线程后启动线程:

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

  8)、第三种创建线程方式:隐式创建并启动线程:

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

  9) 、后面2中创建线程方式的优缺点:

    优点:简单快捷

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

  10)、阻塞(暂停)线程:

    + (void)sleepUnitilDate:(NSDate *)date; //睡眠到date这个时间上

    + (void)sleepForTimeInterval:(NSTimeInterval)seconds;  //睡眠seconds秒

    调用这两个方法中任一方法,当前线程会睡眠(暂停)所设置的时间后,才会执行后面的操作

  11)、强制停止线程,让当前线程提前结束它的生命:+ (void)exit;

7、多线程安全问题 - 互斥锁

  1)、互斥锁使用方式:@synchronized(所对象) { //需要锁定的代码 } ;    // 线程同步:多条线程按顺序地执行任务

  2)、互斥锁的优缺点:

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

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

8、原子和非原子属性

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

  atomic : 院子属性,为setter方法加锁(默认就是atomic)

  nonatomic:非原子属性,不会位setter方法加锁

  ---------------- nontomic 和 atomic对比 -------

  atomic :线程安全,需要消耗大量的资源;

  nonatomic : 非线程安全,适合内存晓得移动设备

  ------ 对于设置属性原子和非原子性的建议 ---

  a、所有属性都声明位nontomic;

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

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

9、线程间通信

  在1个线程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信:比如说一个线程传递数据给另一个线程,又或者在一个线程中执行完成特定任务后,转到另一个线程继续执行任务。

  线程间通信常用方法:

  - (void)performSelectorOnMainThread:(SEL)aSelectorWithObject:(id)arg waitUntilDone:(BOOL)wait; //传递数据到主线程

  - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait; //传递数据到另一个线程

10、GCD

  1)、GCD,全称是Grand Central Dispatch,伟大的中央调度器。纯C语言,提供了非常多强大的函数

  2)、GCD的优势:

    GCD是苹果公司位多核的并行运算提出的解决方案;会自动利用更多的CPU内核;

    会自动管理线程的生命周期(创建线程、调度任务、销毁线程)

  3)、GCD中2个核心概念:任务和队列。任务指执行什么操作,队列是用来存放任务。

    GCD的使用步骤:

      a、定制任务。确定想做的事;

      b、将任务添加到队列中。GCD会自动将队列中的任务取出,放到对应的线程中执行 ;任务的取出遵循队列的FIFO原则:先进先出。

    GCD执行任务函数:

      用同步的方式执行任务:dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);   // queue指队列   ;  block指任务

      用异步的方式执行任务:dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

      同步和异步的区别:同步只能在当前的线程中执行任务,不具备开启新线程的能力; 异步可以在新的线程中执行任务,具备开启新线程的能力;

  4)、队列的类型:主要分为并发队列和串行队列

    并发队列:Concurrent Dispatch Queue, 可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务);

         并发功能只有在异步(dispatch_async)函数下才有效

    串行队列:Serial Dispatch Queue, 让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)

    

    并行队列:

    GCD默认已经提供了全局的并发队列,供整个应用使用,不需要手动创建;

    使用dispatch_get_global_queue函数获得全局的并发队列;

    dispatch_queue_t dispatch_get_global_queue(dispatch_queue_priority_t priority,  unsigned long flags);  //priority指队列的优先级, flags参数暂时无用,用0即可

    示例:dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,  0); //获得全局并发队列  

    全局并发队列的优先级:

    #define DISPATCH_QUEUE_PRIORITY_HIGH  2//高

    #define DISPATCH_QUEUE_PRIORITY_DEFAULT  0//默认(中)

    #define DISPATCH_QUEUE_PRIORITY_LOW (-2)  //低

    #define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN  //后台

    串行队列:

    使用dispatch_queue_create函数创建一个串行队列

    dispatch_queue_create(const char *lable, dispatch_queue_attr_t attr); //lable参数指队列名称;attr参数指队列属性,一般用NULL即可

    另外可以使用主队列:dispatch_get_main_queue(),主队列是GCD自带的一种特殊的串行队列;放在主队列中的任务,都会放到主线程中执行

-----------------------------------------------------

线程和队列、异步同步函数的关系?

1、一个应用程序表示开启了一个进程

2、一个进程至少有一个线程,即至少有一个主线程,也可以开启多条线程

3、一个线程中可以有多个队列,每个队列中可以执行多个任务

4、在线程中执行任务的顺序可以是按顺序来执行,也可以用不按顺序来执行。即表现为串行和并行

5、那异步和同步函数的作用在哪里?

是否开启多条线程,然后执行的队列(任务)是否按顺序还是不按顺序执行,都需要异步和同步函数的配合才能实现!

并行和串行队列,与异步同步函数的排列组合有如下这些:

a、并行队列 + 异步函数 开启多条线程,不按顺序执行任务;

b、串行队列 + 异步函数 开启一条新线程,按顺序执行任务;

c、主队列 + 异步函数不开启新线程,按顺序执行任务

d、并行队列 + 同步函数不开启新线程,按顺序执行任务;

e、串行队列 + 同步函数不开启新线程,按顺序执行任务;

f、主队列 + 同步函数会出现卡死现象!原因:循环等待,主队列的东西要等主线程执行完,又不能开线程,

所以下面的任务要等上面的任务执行完,然后卡死

举例说明:

1、并行队列 + 异步函数:开启多条线程,不按顺序执行任务 (全局队列+异步函数效果一样)

dispatch_queue_t q1 = dispatch_queue_create("mulQueue", DISPATCH_QUEUE_CONCURRENT);
for (int i = ; i < ; i++){
dispatch_async(q1, ^{
NSLog(@"并行+异步,i=%d, currentThread: %@", i, [NSThread currentThread]);
});
}
NSLog(@"并行队列+异步函数测试执行 end....");
/*
并行队列+异步函数测试执行 end....
并行+异步,i=1, currentThread: <NSThread: 0x60000026ab80>{number = 5, name = (null)}
并行+异步,i=0, currentThread: <NSThread: 0x600000269b00>{number = 3, name = (null)}
并行+异步,i=4, currentThread: <NSThread: 0x60000026ea80>{number = 7, name = (null)}
并行+异步,i=3, currentThread: <NSThread: 0x600000269bc0>{number = 6, name = (null)}
并行+异步,i=5, currentThread: <NSThread: 0x60800026d8c0>{number = 8, name = (null)}
....
并行+异步,i=97, currentThread: <NSThread: 0x600000272f80>{number = 49, name = (null)}
并行+异步,i=99, currentThread: <NSThread: 0x600000273000>{number = 50, name = (null)}
并行+异步,i=98, currentThread: <NSThread: 0x60000026ad40>{number = 11, name = (null)}
*/

2、并行 + 同步:不开启线程,按顺序执行,在主线程执行

dispatch_queue_t q2 = dispatch_queue_create("mulQueue", DISPATCH_QUEUE_CONCURRENT);
for (int i = ; i < ; i++){
dispatch_sync(q2, ^{
NSLog(@"并行+同步,i=%d, currentThread: %@", i, [NSThread currentThread]);
});
}
NSLog(@"并行队列+同步函数测试执行 end....");
/*
并行+同步,i=0, currentThread: <NSThread: 0x608000079040>{number = 1, name = main}
并行+同步,i=1, currentThread: <NSThread: 0x608000079040>{number = 1, name = main}
并行+同步,i=2, currentThread: <NSThread: 0x608000079040>{number = 1, name = main}
....
并行+同步,i=97, currentThread: <NSThread: 0x608000079040>{number = 1, name = main}
并行+同步,i=98, currentThread: <NSThread: 0x608000079040>{number = 1, name = main}
并行+同步,i=99, currentThread: <NSThread: 0x608000079040>{number = 1, name = main}
并行队列+同步函数测试执行 end....
*/

3、串行 + 异步:开启一条新线程,按顺序执行

dispatch_queue_t q3 = dispatch_queue_create("singleQueue", NULL);
for (int i = ; i < ; i++){
dispatch_async(q3, ^{
NSLog(@"串行+异步,i=%d, currentThread: %@", i, [NSThread currentThread]);
});
}
NSLog(@"串行队列+异步函数测试执行 end....: %@", [NSThread currentThread]);
/*
串行+异步,i=0, currentThread: <NSThread: 0x60000007f240>{number = 3, name = (null)}
串行队列+异步函数测试执行 end....: <NSThread: 0x60800007b800>{number = 1, name = main}
串行+异步,i=1, currentThread: <NSThread: 0x60000007f240>{number = 3, name = (null)}
串行+异步,i=2, currentThread: <NSThread: 0x60000007f240>{number = 3, name = (null)}
....
串行+异步,i=97, currentThread: <NSThread: 0x60000007f240>{number = 3, name = (null)}
串行+异步,i=98, currentThread: <NSThread: 0x60000007f240>{number = 3, name = (null)}
串行+异步,i=99, currentThread: <NSThread: 0x60000007f240>{number = 3, name = (null)}
*/

4、主队列 + 异步:不开启新线程,按顺序执行

dispatch_queue_t q4 = dispatch_get_main_queue();
for (int i = ; i < ; i++){
dispatch_async(q4, ^{
NSLog(@"主队列+异步,i=%d, currentThread: %@", i, [NSThread currentThread]);
});
}
NSLog(@"主队列+异步函数测试执行 end....: %@", [NSThread currentThread]);
/*
主队列+异步函数测试执行 end....: <NSThread: 0x60000006fe00>{number = 1, name = main}
主队列+异步,i=0, currentThread: <NSThread: 0x60000006fe00>{number = 1, name = main}
主队列+异步,i=1, currentThread: <NSThread: 0x60000006fe00>{number = 1, name = main}
主队列+异步,i=2, currentThread: <NSThread: 0x60000006fe00>{number = 1, name = main}
....
主队列+异步,i=97, currentThread: <NSThread: 0x60000006fe00>{number = 1, name = main}
主队列+异步,i=98, currentThread: <NSThread: 0x60000006fe00>{number = 1, name = main}
主队列+异步,i=99, currentThread: <NSThread: 0x60000006fe00>{number = 1, name = main}
*/

ios线程和GCD和队列同步异步的关系的更多相关文章

  1. ios线程和GCD

    1.什么是进程? 进程是指在系统中正在运行的一个应用程序.比如同时打开QQ.Xcode,系统就会分别启动2个进程.截图 2.什么是线程? 1).一个进程要想执行任务,必须得有线程(每一个进程至少要有一 ...

  2. IOS多线程知识总结/队列概念/GCD/主队列/并行队列/全局队列/主队列/串行队列/同步任务/异步任务区别(附代码)

    进程:正在进行中的程序被称为进程,负责程序运行的内存分配;每一个进程都有自己独立的虚拟内存空间 线程:线程是进程中一个独立的执行路径(控制单元);一个进程中至少包含一条线程,即主线程 队列 dispa ...

  3. iOS GCD基础篇 - 同步、异步,并发、并行的理解

    1.关于GCD - GCD全称是Grand Central Dispatch  - GCD是苹果公司为多核的并行运算提出的解决方案  - GCD会自动利用更多的CPU内核(比如双核.四核)  - GC ...

  4. iOS中的GCD线程

    一.什么是GCD      全称是Grand Central Dispatch ,纯C语言编写,提供非常多强大的函数,是目前苹果官网推荐的多线程开发方法,NSOperation 便是基于GCD的封装 ...

  5. IOS线程的一些总结

    主线程的作用 (在主线程中才能设置) 显示/刷新UI界面 处理UI事件(比如点击事件.滚动事件.拖拽事件): 主线程的使用注意 别将比较耗时的操作放到主线程中. 耗时操作会卡住主线程.影响体验. [N ...

  6. [iOS]深入理解GCD

    看到一篇很好的文章,本来想翻译的,但发现已经有人翻译了,遂简单整理了一下,方便阅读学习 新博客[wossoneri.com] 什么是GCD GCD(Grand Central Dispatch)是li ...

  7. [iOS]多线程和GCD

    新博客wossoneri.com 进程和线程 进程 是指在系统中正在运行的一个应用程序. 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内. 比如同时打开QQ.Xcode,系统就会分别 ...

  8. iOS开发之GCD基础

    重新回顾.学习GCD.Block.先贴出一篇不错的讲解GCD基础使用的文章 原文地址:http://blog.csdn.net/aolan1108/article/details/17283415 做 ...

  9. iOS实录:GCD使用小结(一)

    导语:在iOS中,多线程方案有四种:pthread.NSThread.NSOperation & NSOperationQueue 和 GCD,但是开发中GCD使用得最多,本文主要总结一下我使 ...

随机推荐

  1. 【转】Leveldb源码分析——1

    先来看看Leveldb的基本框架,几大关键组件,如图1-1所示. Leveldb是一种基于operation log的文件系统,是Log-Structured-Merge Tree的典型实现.LSM源 ...

  2. jquery获取、设置、删除cookie

    获取cookie: function getCookie(cname) { var name = cname + "="; var ca = document.cookie.spl ...

  3. event & signals & threads

    The Event Systemhttp://doc.qt.io/qt-4.8/eventsandfilters.html Each thread can have its own event loo ...

  4. 如何查看当前应用包名和activity

    这里提供一个简单的方法来获取package和activity: 在Android模拟器上打开微信APP,然后打开CMD,输入以下命令: adb shell 接下来在#后面继续输入以下命令: logca ...

  5. 接口签名进行key排序,并MD5加密

    import org.apache.commons.codec.digest.DigestUtils; import java.io.UnsupportedEncodingException; imp ...

  6. 转:vw适配中使用伪类选择器遇到的问题

    地址:https://blog.csdn.net/perryliu6/article/details/80965734 在使用vue init webpack构建的项目中,一开始我准备使用rem布局, ...

  7. The word 'localhost' is not correctly spelled 这个问题怎么解决

    The word 'localhost' is not correctly spelled 这个问题怎么解决 有时工程中有下划线并提示 The word is not correctly spelle ...

  8. git reset --hard xxxxxxx

    关于git reset --hard xxxxxxx命令之Git版本回退 今晚代码写着写着就头脑有点发懵,手指也不听使唤了竟然让我敲出了 git reset --hard 命令,然后的然后就是之前所有 ...

  9. Confluence 6 查看空间活动

    空间活动信息是默认禁用(disabled by default)的.活动(Activity)的标没有显示,如果你的 Confluence Usage Stats  插件没有启用的.请查看下面的说明: ...

  10. leetcode(js)算法89之格雷编码

    格雷编码是一个二进制数字系统,在该系统中,两个连续的数值仅有一个位数的差异. 给定一个代表编码总位数的非负整数 n,打印其格雷编码序列.格雷编码序列必须以 0 开头 示例 1: 输入: 2 输出: [ ...