多线程编程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程编程相关的知识,希望对你有一定的参考价值。

1.一些基本概念
 

程序:由源代码生成的可执行应用。(例如:QQ.app)


进程:一个正在运行的程序可以看做一个进程(例如:正在运行的QQ就是一个进程),进程拥有独立运行所需要的全部资源(进程是资源分配的最小单位),每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内。
 
线程:程序中独立运行的代码片段(例如:接受QQ消息的代码),线程是进程的基本执行单元,一个进程(程序)的所有任务都在线程中执行,在同一时间内,1个线程只能执行1个任务
 
一个进程是由一个或者多个线程组成的,进程只负责资源的分配,线程才是程序真正的执行单位,负责代码的执行。
 
单线程:每个正在运行的程序(即进程),至少包含一个线程,这个线程叫主线程。主线程在程序启动时被创建,用于执行main函数,只有一个主线程的程序,称作单线程程序。主线程负责执行程序的所有代码(UI展现以及刷新,网络请求,本地存储等等),这些代码只能顺序执行(一个方法执行完了另一个方法才能执行),无法并发执行。
所谓并发执行:如果有优先级的话:优先级高的方法开始执行的瞬间,另一个方法也执行,如果没有优先级:所有方法同时执行。
 
注意: apple 设置的主线程优先级最高,将所有的UI放在主线程处理, 这样带来的好处就是保证画面流畅度。
 
多线程:拥有多个线程的的程序,称作多线程程序。ios允许用户自己开辟新的线程,相对于主线程来讲,称作子线程,可以根据需要来开辟若干子线程,子线程和主线程都是独立运行的运行单元,各自的执行互不影响,因此能够并发执行。
 
单、多线程的区别
单线程程序:只有一个线程,代码顺序执行,容易出现代码阻塞(页面假死)
多线程程序:有多个线程,线程间独立运行,能有效的避免代码阻塞,并且提高程序的运行性能。
注意:iOS中关于UI的添加和刷新必须在主线程中操作
 
iOS多线程实现种类:NSThread、NSOperationQueue、NSObject、GCD  (具体实现看代码)
注意:在应用程序打开的系统会自动为主线程(.main文件中)创建一个自动释放池,我们手动创建的子线程需要我们自己动手添加自动释放池。
 
NSThread:NSThread是一个轻量级的多线程。
NSThread的常用方法 
??????????????????????????// ????????????????????????判断当前线程是否为多线程 
+ (BOOL)isMultiThreaded; 
// ????????????????获取当前线程对象 
+ (NSThread *)currentThread; 
// ??????????????????????????????????使当前线程睡眠指定的时间,单位为秒 
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;  
// ????????????退出当前线程 
+ (void)exit; 
// ????????????????????????判断当前线程是否为主线程 
+ (BOOL)isMainThread 
// ??????????启动该线程 
- (void)start 
 
NSOperation:NSOperation是一个抽象类,在MVC中属于M,是用来封装单个任务相关的代码和数据的。因为它是抽象的,不能够直接使用这个类,而是使用其子类(NSInvocationOperation、NSBlockOperation)来执行实际任务。NSOperation(含子类),只是一个操作,本身无主线程、子线程之分,可在任意线程中使用,通常于NSOperationQueue结合使用。
NSinvocationOperation:NSinvocationOperation是NSOperation的子类,把执行操作的target和要执行的action封装成了其实例对象。
NSBlockOperation:NSBlockOperation是NSOperation的子类,把需要执行的代码块封装成了其实例对象。
NSOperationQueue:NSOperationQueue是操作队列,他用来管理一组Operation对象的执行,会根据需要自动为Operation对象开辟合适数量的线程,以完成任务的并发执行。当最大并发数设置为1的时候,能实现线程同步。(同步就是协同步调,按预定的先后次序进行运行。如:你说完,我再说。)
 
NSObject实现异步后台执行:NSObject中存在了一个最简单的后台执行方法- (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg
 
GCD:Grand Central Dispatch 简称GCD ,是苹果公司开发的技术。以优化应用程序支持多核心处理器和其他的对称多处理系统的系统。GCD属于函数级的多线程,性能更高,功能也更加强大。
 
GCD核心概念:
任务:具有一定功能的代码段,一般是一个block或者函数。
分发队列:GCD以队列的方式进行工作,FIFO(First Input First Output的缩写)。
GCD会根据分发队列的类型,创建合适数量的线程执行队列中的任务。(serial队列一条线程)
GCD中的两种队列:
SerialQueue:一次只执行一个任务,Serial queue通常用于同步访问特定的资源或者数据。当你创建多个Serial queue时,虽然它们各自是同步执行的,但是Serial queue 与Serial queue之间是并发执行的。SerialQueue能实现线程同步。
Concurrent:可以并发执行多个任务。
注意:这两种队列都遵守先提交的先执行原则。
 
GCD功能:
dispatch_async() //往队列中添加任务,任务会排队执行(FIFO)
dispatch_after() //往队列中添加任务,任务不但会排队,还会在延迟的时间点执行
dispatch_apply() //往队列中添加任务,任务会重复执行n次
dispatch_group_async() //将任务添加到队列中,并添加分组标记
dispatch_group_notify() //将任务添加到队列中,当某个分组的所有的所有任务执行完以后,此任务才会执行
dispatch_barrier_async() //将任务添加到队列中,此任务执行的时候,其他任务停止执行
dispatch_once() //将任务添加到队列中,当任务在程序运行过程中,只执行一次
dispatch_async_f() //将任务添加到队列中,任务是函数而非block
dispatch_sync() //将任务添加到队列中,任务会排队在当前线程执行,(任务)block不执行完,位于它下面的代码就不会执行
   
        注意:
dispatch_async 异步调用:是将block发送到指定线程去执行,当前线程不会等待,直接return,会继续向下执行代码。
dispatch_sync 同步调用:也是将block发送到当前的线程去执行,等待block在当前线程执行完成后才会继续向下执行代码。
 
主队列:是和主线程相关联的队列,主队列是GCD自带的一种特殊的串行队列,放在主队列中得任务,都会放到主线程中执行。 
提示:如果把任务放到主队列中进行处理,那么不论处理函数是异步的还是同步的都不会开启新的线程。 
获取主队列的方式:  dispatch_queue_t queue=dispatch_get_main_queue();
 
使用同步函数,在主线程中执行主队列中得任务,会发生死循环,任务无法往下执行。示意图如下:

技术分享

 
 
 
线程间通信分为两种:主线程进入子线程,子线程回到主线程。
返回主线程的方式:
 1.GCD:dispatch_get_main_queue() 
 2.NSObject:- (void)performSelectorOnMainThread:(SEL)aSelector
withObject:(id)arg waitUntilDone:(BOOL)wait
 
线程互斥:线程互斥是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性,互斥无法限制访问者对资源的访问顺序,即访问是无序的,因此需要加上互斥锁来进行顺序访问。
 
多线程尽管提升了性能,但是存在一些访问限制,比如线程同步,线程互斥。
 
 

以上是关于多线程编程的主要内容,如果未能解决你的问题,请参考以下文章

VB.net多线程编程问题

多线程实践—Python多线程编程

多线程多进程和线程池编程

多线程编程学习笔记——线程池

多线程编程学习笔记——线程同步

python --- 基础多线程编程