标签:
概述
程序:
一个可以运行的文件(我们写的代码)
进程
是程序执行的一个操作实体
在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 比如同时打开QQ、Xcode,系统就会分别启动2个进程
通过“活动监视器”可以查看Mac系统中所开启的进程
线程:(Thread)线程是进程的基本执行单元,一个进程(程序)的所有任务都在线程中执行
一个进程要想执行任务,必须得有线程(每1个进程至少要有1条线程)
比如使用酷狗播放音乐、使用迅雷下载电影,都需要在线程中执行
线程的串行
1个线程中任务的执行是串行的
如果要在1个线程中执行多个任务,那么只能一个一个地按顺序执行这些任务
也就是说,在同一时间内,1个线程只能执行1个任务
比如在1个线程中下载3个文件(分别是文件A、文件B、文件C)
这篇文章中,我不会说多线程是什么、线程和进程的区别、多线程有什么用,当然我也不会说什么是串行、什么是并行等问题,这些我们应该都知道的。
多线程
同一时间,CPU只能处理1条线程,只有1条线程在工作(执行)
多线程并发(同时)执行,其实是CPU快速地在多条线程之间调度(切换)
如果CPU调度线程的时间足够快,就造成了多线程并发执行的假象
如果线程非常多,会出现什么效果?
cpu在很多的线程之间切换,cpu会被累死,消耗了太多的cpu资源,单次执行线程的间隔越来越长,频次越来越低,任务执行效率也就越低。
那么多线程有什么优点和缺点呢?
1.多线程的优点:1)能适当地提高程序的执行效率。2)能适当提高资源利用率。(比如cpu,内存等)
2.多线程的缺点:1)开启线程需要占用一定的内存空间。默认情况下,主线程占用1M 子线程占用512KB 如果开启了大量的线程,会占用大量的内存空间 降低程序性能。2)线程越多,cpu在调度线程上的开销越大。3)线程设计更加复杂,比如线程之间的通信多线程的数据共享。
3.多线程在iOS开发中的应用
主线程:一个iOS程序运行之后,默认会开启一条线程,称之为 主线程或者UI线程。
主线程的主要作用:刷新界面,显示界面 处理UI事件。
主线程的使用注意点:不要把比较耗时间的操作放到主线程中。 耗时操作会卡住主线程,严重影响UI的流畅度。
iOS线程模型
pthread 底层的c线程库
NSThread oc线程库
NSOperationQueue 线程队列
Blocks/GCD
主线程处理 工程1 耗时操作
点击事件 -(IBAction)threadDoWork:(id)sender { int i = 0; while (i++ <10) { NSLog(@"%@",@"好吧 我开始工作了"); [NSThread sleepForTimeInterval:1.0];
NSLog(@"%@",[NSThread currentThread]); } NSLog(@"%@",@"完成了"); }
//再加一个 //耗时操作 -(IBAction)threadDoSleep:(id)sender { int i = 0; while (i++ <10) { //线程休眠 //这里并没有开辟新线程,那么休眠的是主线程。 //哪个线程执行sleep休眠的是哪个 //响应UI事件的是在主线程 [NSThread sleepForTimeInterval:1.0]; NSLog(@"%@",@"我睡着了 不要烦我"); } NSLog(@"%@",@"睡醒了"); }
添加两个按钮,btn1事件触发工作,btn2事件触发睡觉。
当我点击相应的按钮之后,会有相应的输出。总结:
1)主线程相应我们操作。
2)主线程处理任务,都是按照自然顺序处理,谁先来处理谁,在一件事没有处理完成之前,它不会去处理其他的事情。
3) currentThread是当前线程,获得当前逻辑代码是在那个线程中。
4)主线程的number =1 name=main
那么问题来了,既然响应在主线程中进行处理,那么如果耗时操作的数据量和处理特别复杂时 当前的界面会变的很卡很卡。该怎么解决这个问题呢?答案是多线程。
主线程上执行的操作最好都是及时响应的,不能让用户觉得我们的程序卡死,那样使得用户体验很不好。
那么这样的耗时操作我们应该放在哪里呢?答案是子线程。1)一定不要在子线程中做这件事。2)开启一条新的线程来完成耗时操作。
接下来讨论子线程。
1.pthread 用c方法创建子线程。主要方法:
pthread_t cThread;
int b = pthread_create(&cThread, NULL, working, NULL);
限制性:只能开线程。不能控制。
2.NSThread
官方定义:
NSThread定义 @interface NSThread : NSObject { @private id _private; uint8_t _bytes[44]; } + (NSThread *)currentThread;//当前的线程 {number name} + (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;//类方法 将操作直接添加到线程中运行。 + (BOOL)isMultiThreaded;//是否是多线程工作模式? @property (readonly, retain) NSMutableDictionary *threadDictionary; + (void)sleepUntilDate:(NSDate *)date;//休眠直到date + (void)sleepForTimeInterval:(NSTimeInterval)ti;//休眠ti秒 + (void)exit;//退出。 + (double)threadPriority;//优先级 + (BOOL)setThreadPriority:(double)p;//方法设置优先级 @property double threadPriority NS_AVAILABLE(10_6, 4_0); // To be deprecated; use qualityOfService below @property NSQualityOfService qualityOfService NS_AVAILABLE(10_10, 8_0); // read-only after the thread is started + (NSArray *)callStackReturnAddresses NS_AVAILABLE(10_5, 2_0); + (NSArray *)callStackSymbols NS_AVAILABLE(10_6, 4_0); @property (copy) NSString *name NS_AVAILABLE(10_5, 2_0);//属性:线程名称 @property NSUInteger stackSize NS_AVAILABLE(10_5, 2_0); @property (readonly) BOOL isMainThread NS_AVAILABLE(10_5, 2_0); + (BOOL)isMainThread NS_AVAILABLE(10_5, 2_0); //判断当前线程是否是主线程 + (NSThread *)mainThread NS_AVAILABLE(10_5, 2_0);获取主线程 - (instancetype)init NS_AVAILABLE(10_5, 2_0) NS_DESIGNATED_INITIALIZER; - (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(id)argument NS_AVAILABLE(10_5, 2_0);//初始化的同时添加操作,并执行。 @property (readonly, getter=isExecuting) BOOL executing NS_AVAILABLE(10_5, 2_0); @property (readonly, getter=isFinished) BOOL finished NS_AVAILABLE(10_5, 2_0);//判断是否完成任务? @property (readonly, getter=isCancelled) BOOL cancelled NS_AVAILABLE(10_5, 2_0);// - (void)cancel NS_AVAILABLE(10_5, 2_0); - (void)start NS_AVAILABLE(10_5, 2_0); - (void)main NS_AVAILABLE(10_5, 2_0); // thread body method @end FOUNDATION_EXPORT NSString * const NSWillBecomeMultiThreadedNotification; FOUNDATION_EXPORT NSString * const NSDidBecomeSingleThreadedNotification; FOUNDATION_EXPORT NSString * const NSThreadWillExitNotification; @interface NSObject (NSThreadPerformAdditions) - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array; - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; // equivalent to the first method with kCFRunLoopCommonModes - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array NS_AVAILABLE(10_5, 2_0); - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0); // equivalent to the first method with kCFRunLoopCommonModes - (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg NS_AVAILABLE(10_5, 2_0); @end
用NSThread创建单个线程
#pragma mark -创建线程 单个 -(void)createThread { // 类方法 /* [NSThread detachNewThreadSelector:@selector(doWorking) toTarget:self withObject:nil]; */ //对象方法 /* NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(doToilet) object:nil]; */ //NSThread 是cocoa(macOS,iOS)中一个轻量级的线程对象。 NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(doToilet) object:nil]; thread.name = @"我的线程"; //使用alloc创建的线程 一定要调用start方法,才能运行。 [thread start]; //类方法 [NSThread detachNewThreadSelector:@selector(doWorking) toTarget:self withObject:nil]; //类方法退出,以下代码不会执行。 //[NSThread exit]; NSLog(@"%@",@"-s-s-s-"); }
#pragma mark -任务 -(void)doWorking { int i = 0; while (i++ <10) { //获取当前线程 NSThread *thread = [NSThread currentThread]; NSLog(@"%@学习了%d秒",thread.name,i); [NSThread sleepForTimeInterval:1.0]; } NSLog(@"%@",@"完成了"); }
让线程做多件事情
-(IBAction)doWorking:(id)sender{ // [self doWorking]; [self createThreads:0]; } -(IBAction)doWCing:(id)sender{ // [self doWCing]; // [self createThread]; [self createThreads:1]; }点击触发
-(void)createThreads:(int)n{ switch (n) { case 0: //创建多个工作的线程 for (NSInteger i = 0; i<3; i++) { //开辟工作线程 NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(doWorking) object:nil]; //可以给线程取个名字,加以区分 [thread setName:[NSString stringWithFormat:@"工作线程%ld号",i+1]]; //设置线程的优先级 thread.threadPriority = i+1; //作用并不明显,并不能控制线程的顺序 [thread start]; } break; case 1: //创建多个工作的线程 for (NSInteger i = 0; i<3; i++) { //开辟工作线程 NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(doWCing) object:nil]; //可以给线程取个名字,加以区分 [thread setName:[NSString stringWithFormat:@"工作线程%ld号",i+1]]; //设置线程的优先级 thread.threadPriority = i+1; //作用并不明显,并不能控制线程的顺序 [thread start]; } break; default: break; } }
对资源加锁
-(void)doWorking{ int i = 0; while (i++<10) { //获取当前的线程 NSThread *thread = [NSThread currentThread]; NSLog(@"%@学",thread.name,i); [NSThread sleepForTimeInterval:1.0]; } NSLog(@"完成"); } /** * */ -(void)doWCing{ if(_threadLock == nil){ _threadLock = [[NSLock alloc]init]; } //上锁 [_threadLock lock]; @synchronized(self){ int i = 0; while (i++<10) { //获取当前的线程 NSThread *thread = [NSThread currentThread]; NSLog(@"%@%d秒",thread.name,i); [NSThread sleepForTimeInterval:1.0]; } NSLog(@"完成"); } //解锁 [_threadLock unlock]; }
然而 NSThread难于人为地去控制创建子线程的数量。子线程创建过多,会严重地影响程序的性能,因为每一个线程都会占用一定cpu的资源,导致cpu很忙碌。
那么怎么解决这个问题?用GCD。
下一章讨论GCD的内容。
标签:
原文地址:http://www.cnblogs.com/mosuyanxue/p/4811721.html