疯狂iOS讲义(下)之多线程

疯狂iOS讲义下:


第七章:多线程


本章要点:

多线程知识和多线程优势

使用NSThread创建和启动线程

线程的状态

终止子线程

线程睡眠

改变线程优先级

iOS应用开发中线程安全问题

使用@synchronized实现同步

释放同步监视器的锁定

同步锁(NSLock

使用NSCondition控制线程通信

实例:生产者-消费者

使用GCD实现多线程

异步提交任务

使用GCD同步提交任务

使用GCD提交多次执行的任务

使用GCD提交只执行一次的任务

控制iOS应用在后台运行

控制iOS应用进入后台运行

控制iOS应用进入后台时保存状态

请求更多地后台时间

使用NSOperationNSoperationQueue实现多线程

通过NSOperation子类实现多线程




单线程程序如同只雇用一个服务员的单停,他必须做完一件事情后才能做下一件事情;多线程程序如同雇佣多个服务员的餐厅,他们可以同时进行着多件事情。




每个运行中的程序就是一个进程。当一个程序运行时,内部可能包含了多个顺序执行流,每个顺序执行流就是一个线程。


进程是系统进行资源分配和调度的一个独立单位。


进程的3个特征:

独立性;

动态性:进程和程序的区别在于,程序只是一个静态的指令集合,而进程是一个正在系统中活动的指令集合。进程具有自己的生命周期和各种不同的状态。

并发性:多个进程可以在单个处理器上并发执行,多个进程之间不会互相影响。


注意:并发性和并行性是两个概念,并行是指在同一时刻,有多条指令在多个处理器上同时执行;并发指在同一时刻只能有一条指令执行,但多个进程指令被快速轮换执行,使得在宏观上具有多个进程同时执行的效果。



线程也被称作轻量级进程。线程是进程的执行单元。就像进程在操作系统中的低位一样,线程在程序中是独立的、并发的执行流。当进程被初始化后,主线程就被创建了。对于绝大多数的应用程序来说,通常仅要求有一个主线程,但也可以在该进程内创建多条顺序执行流,这些顺序执行流就是线程,每条线程也是相互独立的。



线程是进程的组成部分,一个进程可以拥有多个线程,一个线程必须有一个父进程。线程可以拥有自己的堆栈、自己的程序计数器和自己的局部变量,但不再拥有系统资源,它与父进程的其他线程共享该进程所有的全部资源。因为多个线程共享父进程里的全部资源,因此编程更加方便;但必须确保线程不会妨碍统一进程里的其他线程。

线程之间相互协同来完成进程所要完成的任务。


线程是独立运行的,它并不知道进程中是否还有其他线程存在。线程的执行是抢占式的,也就是说,当前运行的线程在任何时候都可能被挂起,以便另外一个线程可以运行。


一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行。


操作系统不会将多个线程看做多个独立的应用,对多线程实现调度和资源分配是由进程本身负责完成。


简而言之:一个程序运行后至少有一个进程,一个进程里可以包含多个线程,但至少要包含一个线程。


总结就是:操作系统可以同时执行多个任务,每个任务就是进程;进程可以同时执行多个任务,每个任务就是线程。


1.2 多线程的优势


线程比进程具有更高的性能,是由于同一个进程中的线程都有共性——多个线程将共享同一个进程虚拟空间。下车高共享的环境包括:进程代码段、进程的公有数据等。利用这些共享的数据等,线程很容易实现相互之间的通信。


当操作系统创建一个进程时,必须为该进程分配独立的内存空间,并分配大量的相关资源;但创建一个线程则简单得多,一次使用多线程来实现并发比使用多进程实现并发的性能要高得多。


总结多线程编程的优点:

a. 进程间不能共享内存,但线程之间共享内存非常容易。

b. 系统创建进程需要为该进程重新分配系统资源,但创建线程则代价小得多,因此使用多线程来实现多任务并发比多进程的效率高。

c. iOS提供了多种多线程实现方式,从而简化了iOS的多线程编程。


(主线程又称作UI线程)


iOS大致提供了如下3种多线程编程的技术:

a. 使用NSThread 实现多线程。

b. 使用NSOperation与NSOperationQueue 实现多线程。

c. 使用GCD(Grand Central Dispatch)实现多线程。

这3种多线程编程的技术,抽象度层次是从低到高的,抽象度越高的用法越简单。

理解NSThread才能更好地理解编程的本质与细节。


  1. 使用NSThread实现多线程。

iOS使用NSThread类代表线程,创建县县城也就是创建NSThread对象。

2.1创建和启动线程

创建NSThread有两种方式:

  • (id)initWithTarget:(id)target selector:(SEL)selector object:(id)arg;创建一个新线程对象。

+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target  withObject:(id)arg;创建并启动新线程。


上面两种方式的本质都是将target对象的selector方法转换为线程执行体,其中selector方法最多可以接受一个参数,而arg就代表传给selector方法的参数。

提示:target对象的selector方法的方法体代表了线程需要完成的任务,因此相当于把target对象的selector方法转换为线程执行体。


第一种方法会返回一个NSThread对象,必须要调用start方法启动线程;

第二种方法不会返回NSThread对象,因袭这种方式会直接创建并启动线程。



2.2 线程的状态

【当线程对象调用了start方法之后,该线程出狱就绪状态,系统会为其创建方法调用栈和程序计数器,处于这种状态中的线程并没有开始运行,它只是表示该线程可以运行了。置于该线程何时开始运行,取决于系统的调度。】


启动线程使用start方法,线程启动之后并不是立即进入运行状态,线程被启动后处于就绪状态,当系统调度线程后,线程才会进入运行状态。


2.3 终止子线程

a. 线程执行体方法执行完成,线程正常结束。

b. 线程执行过程中出现了错误。

c. 直接调用NSThread类的exit方法来中止当前正在执行的线程。


注意:当主线程结束时,其他线程不受任何影响,并不会随之结束,一旦子线程启动起来后,它就拥有和主线程相同的地位,他不会受主线程的影响。


2.4 线程睡眠

NSThread类提供了如下两个控制线程暂停的类方法:

+voidsleepUntilDate:(NSDate *aDate;让当前正在执行的线程暂停到aDate代表的时间,并进入阻塞状态。

+voidsleepForTimeInterval:(NSTimeIntervalti;让当前正在执行的线程暂停ti秒,并进入阻塞状态。

当前线程调用睡眠方法进入阻塞状态后,在其睡眠时间段内,该线程不会获得执行的机会,即使系统中没有其他 可执行的线程,处于阻塞状态的线程也不会执行,因此常用来暂停线程的执行。


未完。。。。。

你可能感兴趣的:(疯狂iOS讲义(下)之多线程)