对于开发者来说,多线程永远有这一层神秘的色彩,似乎是一到迈步过去的坎,在同步、异步、串行、并行、死锁这几个名字当中,逐渐的放弃治疗,下面就多线程,谈一下自己的认识,理解的肯定不全面,只是一些简单的皮毛,特在此记录下,哪位大神看到了,还希望能多多指正!

首先:什么是线程,线程和进程的区别和联系

  • 一个程序至少要有进城,一个进程至少要有一个线程.

  • 进程:资源分配的最小独立单元,进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.

  • 线程:进程下的一个分支,是进程的实体,是CPU调度和分派的基本单元,它是比进程更小的能独立运行的基本单位,线程自己基本不拥有系统资源,只拥有一点在运行中必不可少的资源(程序计数器、一组寄存器、栈),但是它可与同属一个进程的其他线程共享进程所拥有的全部资源。

  • 进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。

  • 进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些

什么是多线程编程?

  • NSThread:当需要进行一些耗时操作时会把耗时的操作放到线程中。线程同步:多个线程同时访问一个数据会出问题,NSlock、线程同步块、@synchronized(self){}。

  • NSOperationQueue操作队列(不需考虑线程同步问题)。编程的重点都放在main里面,NSInvocationOperationBSBlockOperation、自定义Operation。创建一个操作绑定相应的方法,当把操作添加到操作队列中时,操作绑定的方法就会自动执行了,当把操作添加到操作队列中时,默认会调用main方法。

  • GCD(`Grand Central Dispatch)宏大的中央调度,串行队列、并发队列、主线程队列;

  • 同步和异步:同步指第一个任务不执行完,不会开始第二个,异步是不管第一个有没有执行完,都开始第二个。

  • 串行和并行:串行是多个任务按一定顺序执行,并行是多个任务同时执行;

  • 代码是在分线程执行,在主线程嘟列中刷新UI。

多线程编程是防止主线程堵塞、增加运行效率的最佳方法。

  • Apple提供了NSOperation这个类,提供了一个优秀的多线程编程方法;

  • 一个NSOperationQueue操作队列,相当于一个线程管理器,而非一个线程,因为你可以设置这个线程管理器内可以并行运行的线程数量等。

  • 多线程是一个比较轻量级的方法来实现单个应用程序内多个代码执行路径。

  • iPhoneOS下的主线程的堆栈大小是1M。第二个线程开始就是512KB,并且该值不能通过编译器开关或线程API函数来更改,只有主线程有直接修改UI的能力。

定时器与线程的区别;

  • 定时器;可以执行多次,默认在主线程中。

  • 线程:只能执行一次。

GCD初始:

一条重要的准则

一般来说,我们使用GCD的最大目的是在新的线程中同时执行多个任务,这意味着我们需要两项条件:

  • 能开启新的线程

  • 任务可以同时执行

  • 结合以上两个条件,也就等价“开启新线程的能力 + 任务同步执行的权利”,只有在满足能力与权利这两个条件的前提下,我们才可以在同时执行多个任务。

所有组合的特点:

各个组合下的代码执行:

//异步执行+并行队列
-(void)asynConcurrent
{
//并行队列
dispatch_queue_t two_queue = dispatch_queue_create("hero.hel.11223", DISPATCH_QUEUE_CONCURRENT); NSLog(@"---start---"); dispatch_async(two_queue, ^{
NSLog(@"任务一---%@",[NSThread currentThread]);
}); dispatch_async(two_queue, ^{
NSLog(@"任务二---%@",[NSThread currentThread]);
}); dispatch_async(two_queue, ^{
NSLog(@"任务三---%@",[NSThread currentThread]);
}); NSLog(@"--end---");
}

打印结果:

-- ::34.500 线程的练习[:] ---start---
-- ::34.501 线程的练习[:] --end---
-- ::34.501 线程的练习[:] 任务一---<NSThread: 0x618000078480>{number = , name = (null)}
-- ::34.501 线程的练习[:] 任务二---<NSThread: 0x60000007d100>{number = , name = (null)}
-- ::34.501 线程的练习[:] 任务三---<NSThread: 0x6180000728c0>{number = , name = (null)} 异步执行意味着:
1、可以开启新的线程
2、任务可以先绕过不执行,回头再来执行 并行队列意味着:
1、任务之间不需要排队,且具有同时被执行的“权利”
两者组合后的结果:
1、开了三个新线程
2、函数在执行时,先打印了start和end,再回头执行这三个任务
3、这三个任务是同时执行,没有先后


 //同步执行+串行队列
-(void)synSerial
{
//串行队列
dispatch_queue_t one_queue = dispatch_queue_create("hero.hgl.112233", DISPATCH_QUEUE_SERIAL); NSLog(@"--开始--"); dispatch_sync(one_queue, ^{
NSLog(@"任务1---%@",[NSThread currentThread]);
}); dispatch_sync(one_queue, ^{
NSLog(@"任务2---%@",[NSThread currentThread]);
}); dispatch_sync(one_queue, ^{
NSLog(@"任务3---%@",[NSThread currentThread]);
}); NSLog(@"--结束--");
}

打印结果:

-- ::34.502 线程的练习[:] --开始--
-- ::34.505 线程的练习[:] 任务1---<NSThread: 0x618000075340>{number = , name = main}
-- ::34.505 线程的练习[:] 任务2---<NSThread: 0x618000075340>{number = , name = main}
-- ::34.506 线程的练习[:] 任务3---<NSThread: 0x618000075340>{number = , name = main}
-- ::34.507 线程的练习[:] --结束-- 这里的执行原理和步骤图跟“同步执行+并发队列”是一样的,只要是同步执行就没法开启新的线程,所以多个任务之间也一样只能按顺序来执行


//异步执行+串行队列
-(void)asynSerial
{
//串行队列
dispatch_queue_t h_queue = dispatch_queue_create("hero112233.com", DISPATCH_QUEUE_SERIAL); NSLog(@"开始了----"); dispatch_async(h_queue, ^{
NSLog(@"a计划 -- %@", [NSThread currentThread]);
}); dispatch_async(h_queue, ^{
NSLog(@"b计划 -- %@", [NSThread currentThread]);
}); dispatch_async(h_queue, ^{
NSLog(@"c计划 -- %@", [NSThread currentThread]);
}); NSLog(@"--结束了---");
}

打印结果:

2017-04-06 15:35:37.916 线程的练习[2376:173399] 开始了----
2017-04-06 15:35:37.916 线程的练习[2376:173399] --结束了---
2017-04-06 15:35:37.916 线程的练习[2376:173459] a计划 -- <NSThread: 0x600000075d00>{number = 3, name = (null)}
2017-04-06 15:35:37.917 线程的练习[2376:173459] b计划 -- <NSThread: 0x600000075d00>{number = 3, name = (null)}
2017-04-06 15:35:37.917 线程的练习[2376:173459] c计划 -- <NSThread: 0x600000075d00>{number = 3, name = (null)}
异步执行意味着:
1、可以开启新的线程
2、任务可以先绕过不执行,回头再来执行
串行队列意味着:
1、任务必须按添加进队列的顺序挨个执行
两者组合后的结果:
1、开启了一个新的子线程
2、函数在执行时,先打印了开始和结束,再回头执行这三个任务
3、三个任务是按顺序执行的,所以打印结果是“任务a-->任务b-->任务c”


//同步执行+并行队列
-(void)synConcurrent
{
//并行队列
dispatch_queue_t r_queue = dispatch_queue_create("aaaa.com", DISPATCH_QUEUE_CONCURRENT); NSLog(@"@@@开始了"); dispatch_sync(r_queue, ^{
NSLog(@"a1计划 -- %@", [NSThread currentThread]);
}); dispatch_sync(r_queue, ^{
NSLog(@"a2计划 -- %@", [NSThread currentThread]);
}); dispatch_sync(r_queue, ^{
NSLog(@"a3计划 -- %@", [NSThread currentThread]);
}); NSLog(@"@@@@结束了");
}

打印结果:

2017-04-06 15:40:24.100 线程的练习[2410:175780] @@@开始了
2017-04-06 15:40:24.135 线程的练习[2410:175780] a1计划 -- <NSThread: 0x6000000734c0>{number = 1, name = main}
2017-04-06 15:40:24.136 线程的练习[2410:175780] a2计划 -- <NSThread: 0x6000000734c0>{number = 1, name = main}
2017-04-06 15:40:24.136 线程的练习[2410:175780] a3计划 -- <NSThread: 0x6000000734c0>{number = 1, name = main}
2017-04-06 15:40:24.136 线程的练习[2410:175780] @@@@结束了 同步执行意味着:
1、不能开启新的线程
2、任务创建后必须执行完才能往下走
并行队列意味着:
1、任务必须按添加进队列的顺序挨个执行
两者结合:
1、所有任务都只能在主线程中执行
2、函数在执行时,必须按照代码的书写顺序一行一行的执行完才能继续
注意:
在这里即便是并行队列,任务可以同时执行,但是由于只存在一个主线程,所以没法把任务分发到不同的线程去同步处理,期结果就是只能在主线程里
按顺序挨个执行了
//异步执行+主队列
-(void)asynmainQueue
{
//主队列
dispatch_queue_t mainQueue = dispatch_get_main_queue(); NSLog(@"@@@start"); dispatch_async(mainQueue, ^{
NSLog(@"a11计划 -- %@", [NSThread currentThread]);
}); dispatch_async(mainQueue, ^{
NSLog(@"a22计划 -- %@", [NSThread currentThread]);
}); dispatch_async(mainQueue, ^{
NSLog(@"a33计划 -- %@", [NSThread currentThread]);
}); NSLog(@"@@@end");
}

打印结果:

-- ::34.532 线程的练习[:] @@@start
-- ::34.532 线程的练习[:] @@@end
-- ::34.708 线程的练习[:] a11计划 -- <NSThread: 0x618000075340>{number = , name = main}
-- ::34.709 线程的练习[:] a22计划 -- <NSThread: 0x618000075340>{number = , name = main}
-- ::34.709 线程的练习[:] a33计划 -- <NSThread: 0x618000075340>{number = , name = main} 异步执行意味着:
1、可以开启新的线程
2、任务可以先绕过去不执行,回头再来执行
主队列和串行队列的区别:
1、队列中的任务一样要按顺序执行
2、主队列中的任务必须在主线程中执行,不允许在子线程中执行


//同步执行+主队列 -->死锁
-(void)synmainQueue
{
//主队列
dispatch_queue_t hmainQueue = dispatch_get_main_queue(); NSLog(@"@@@start"); dispatch_sync(hmainQueue, ^{
NSLog(@"a11计划 -- %@", [NSThread currentThread]);
}); dispatch_sync(hmainQueue, ^{
NSLog(@"a22计划 -- %@", [NSThread currentThread]);
}); dispatch_sync(hmainQueue, ^{
NSLog(@"a33计划 -- %@", [NSThread currentThread]);
}); NSLog(@"@@@end");
}

打印结果:

-- ::06.447 线程的练习[:] @@@start

解释:
1、主队列中的任务必须按顺序挨个执行
2、任务1要等主线程有空的时候(即主队列中的所有任务执行完)才能执行
3、主线程要执行完“end”的任务才有空
4、a11计划和end两个任务互相等等,造成死锁


IOS开发之 -- 线程初识的更多相关文章

  1. iOS开发之线程间的MachPort通信与子线程中的Notification转发

    如题,今天的博客我们就来记录一下iOS开发中使用MachPort来实现线程间的通信,然后使用该知识点来转发子线程中所发出的Notification.简单的说,MachPort的工作方式其实是将NSMa ...

  2. iOS开发系列-线程同步技术

    概述 多线程的本质就是CPU轮流随机分配给每条线程时间片资源执行任务,看起来多条线程同时执行任务. 多条线程同时访问同一块资源,比如操作同一个对象.统一变量.同一个文件,就会引发数据错乱和数据安全的问 ...

  3. iOS开发之线程组解决请求多个接口数据,完成后,再刷新界面

    1.多任务请求接口,完成后,在刷新数据,常用方法 2018年07月18日 16:34:38 hbblzjy 阅读数:1382 版权声明:本文为博主原创文章,未经博主允许不得转载. https://bl ...

  4. iOS开发开辟线程总结--NSThread

    1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue ...

  5. iOS开发多线程-线程间通讯

    一.NSThread 线程间的通讯 - (void)demoAboutNSThread { NSLog(@"demoAboutNSThread %@", [NSThread cur ...

  6. iOS开发系列-线程状态

    概述 线程从创建到销毁中间存在很多种状态. 线程的状态 通过NSThread创建一条线程,开发者需要负责线程的创建和执行,线程的销毁由系统决定.创建一个继承NSThread的FMThread类,重写d ...

  7. iOS开发:(线程篇-上)线程和进程

    iOS开发多线程篇—多线程简单介绍 一.进程和线程 1.什么是进程 进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 比如同时打开QQ.Xcod ...

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

    iOS开发多线程篇—线程安全 一.多线程的安全隐患 资源共享 1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源 比如多个线程访问同一个对象.同一个变量.同一个文件 当多个线程访问同一块 ...

  9. iOS开发多线程篇—创建线程

    iOS开发多线程篇—创建线程 一.创建和启动线程简单说明 一个NSThread对象就代表一条线程 创建.启动线程 (1) NSThread *thread = [[NSThread alloc] in ...

随机推荐

  1. Creating, detaching, re-attaching, and fixing a SUSPECT database

    今天遇到一个问题:一个数据库suspect了.然后又被用户detach了. 1,尝试将数据库attach回去,因为log file损坏失败了. 2,尝试将数据库attach回去,同一时候rebuild ...

  2. JConsole的使用手册 JDK1.5(转)

    一篇Sun项目主页上介绍JConsole使用的文章,前段时间性能测试的时候大概翻译了一下以便学习,今天整理一下发上来,有些地方也不知道怎么翻,就保留了原文,可能还好理解点,呵呵,水平有限,翻的不好,大 ...

  3. html中的标签分类

    单标签 <br> <hr> <img> <input> <param> <meta> <link> 双标签 < ...

  4. 基于C#的控制台的进度提示实现

    在网上搜了很多关键词,比如C#控制台如何删除上一行输出,C#如何控制台删除部分内容,但是都没有很好的教程. 所以自己动手研究一下.也不是什么高深的东西,如下: 用C#开发了一个爬虫下载器,为了知道还剩 ...

  5. js 时间戳

    https://www.cnblogs.com/crf-Aaron/archive/2017/11/16/7844462.html var time = '2018-03-22 00:00:00'.r ...

  6. atitit.php中的dwr 设计模式

    atitit.php中的dwr 设计模式 1. dwr的优点相对于ajax来说.. 1 2. DWR工作原理 1 3. php的dwr实现 1 4. 参考 3 1. dwr的优点相对于ajax来说.. ...

  7. maven添加额外archetype

    用Eclipse + m2e 插件新建maven项目时发现archetype太少了,网上搜索如何添加额外的archetype. http://maven.apache.org/archetype/ma ...

  8. InnoDB: auto-extending data file ./ibdata1 is of a different size 640 pages (rounded down to MB) than specified in the .cnf file: initial 768 pages, max 0 (relevant if non-zero) pages!

    问题描述: centos 安装MySQL $yum install mysql-server 安装之后执行命令mysql 报错: 查看mysql的启动日志: [ERROR] InnoDB: auto- ...

  9. Paxos发展、算法原理

    Paxos 发展史 Leslie Lamport所提出的Paxos算法是现代分布式系统中的一项重要的基础性技术,得到广泛的应用. Paxos的整个发展过程大概可以分为三个阶段: 第一阶段:萌芽期,大致 ...

  10. Taxi Cab Scheme UVALive - 3126 最小路径覆盖解法(必须是DAG,有向无环图) = 结点数-最大匹配

    /** 题目:Taxi Cab Scheme UVALive - 3126 最小路径覆盖解法(必须是DAG,有向无环图) = 结点数-最大匹配 链接:https://vjudge.net/proble ...