iOS面试题合集(多线程篇)

iOS面试题合集(多线程篇)

2023年8月1日发(作者:)

iOS⾯试题合集(多线程篇)⽬录:1.进程与线程分别是什么意思?2.什么是多线程?3.多线程的优点和缺点有哪些?4.多线程的 并⾏ 和 并发 有什么区别?中实现多线程的⼏种⽅案,各⾃有什么特点?6.多个⽹络请求完成后如何执⾏下⼀步?7. 多个⽹络请求顺序执⾏后如何执⾏下⼀步?8.如何理解多线程中的死锁?9.如何去理解GCD执⾏原理?1.进程与线程分别是什么意思?进程:1.进程是⼀个具有⼀定独⽴功能的程序关于某次数据集合的⼀次运⾏活动,它是操作系统分配资源的基本单元.2.进程是指在系统中正在运⾏的⼀个应⽤程序,就是⼀段程序的执⾏过程,我们可以理解为⼿机上的⼀个app.3.每个进程之间是独⽴的,每个进程均运⾏在其专⽤且受保护的内存空间内,拥有独⽴运⾏所需的全部资源线程1.程序执⾏流的最⼩单元,线程是进程中的⼀个实体.2.⼀个进程要想执⾏任务,必须⾄少有⼀条线程.应⽤程序启动的时候,系统会默认开启⼀条线程,也就是主线程进程和线程的关系1.线程是进程的执⾏单元,进程的所有任务都在线程中执⾏2.线程是 CPU 分配资源和调度的最⼩单位3.⼀个程序可以对应多个进程(多进程),⼀个进程中可有多个线程,但⾄少要有⼀条线程4.同⼀个进程内的线程共享进程资源2.什么是多线程?多线程的实现原理:事实上,同⼀时间内单核的CPU只能执⾏⼀个线程,多线程是CPU快速的在多个线程之间进⾏切换(调度),造成了多个线程同时执⾏的假象。如果是多核CPU就真的可以同时处理多个线程了。多线程的⽬的是为了同步完成多项任务,通过提⾼系统的资源利⽤率来提⾼系统的效率。3.多线程的优点和缺点有哪些?优点:能适当提⾼程序的执⾏效率能适当提⾼资源利⽤率(CPU、内存利⽤率)缺点:开启线程需要占⽤⼀定的内存空间(默认情况下,主线程占⽤1M,⼦线程占⽤512KB),如果开启⼤量的线程,会占⽤⼤量的内存空间,降低程序的性能线程越多,CPU在调度线程上的开销就越⼤程序设计更加复杂:⽐如线程之间的通信、多线程的数据共享4.多线程的 并⾏ 和 并发 有什么区别?并⾏:充分利⽤计算机的多核,在多个线程上同步进⾏并发:在⼀条线程上通过快速切换,让⼈感觉在同步进⾏中实现多线程的⼏种⽅案,各⾃有什么特点?NSThread ⾯向对象的,需要程序员⼿动创建线程,但不需要⼿动销毁。⼦线程间通信很难。GCD c语⾔,充分利⽤了设备的多核,⾃动管理线程⽣命周期。⽐NSOperation效率更⾼。NSOperation 基于gcd封装,更加⾯向对象,⽐gcd多了⼀些功能。6.多个⽹络请求完成后如何执⾏下⼀步?使⽤GCD的dispatch_group_t创建⼀个dispatch_group_t每次⽹络请求前先dispatch_group_enter,请求回调后再dispatch_group_leave,enter和leave必须配合使⽤,有⼏次enter就要有⼏次leave,否则group会⼀直存在。当所有enter的block都leave后,会执⾏dispatch_group_notify的block。NSString*str=@"/";NSURL*url=[NSURL URLWithString:str];NSURLRequest*request=[NSURLRequest requestWithURL:url];NSURLSession*session=[NSURLSession sharedSession];dispatch_group_t downloadGroup=dispatch_group_create();for(inti=0;i<10;i++){dispatch_group_enter(downloadGroup);NSURLSessionDataTask*task=[session dataTaskWithRequest:request completionHandler:^(NSData*_Nullabledata,NSURLResponse*_Nullable response,NSError*_Nullable error){NSLog(@"%d---%d",i,i);dispatch_group_leave(downloadGroup);}];[task resume];}dispatch_group_notify(downloadGroup,dispatch_get_main_queue(),^{NSLog(@"end");});使⽤GCD的信号量dispatch_semaphore_tdispatch_semaphore信号量为基于计数器的⼀种多线程同步机制。如果semaphore计数⼤于等于1,计数-1,返回,程序继续运⾏。如果计数为0,则等待。dispatch_semaphore_signal(semaphore)为计数+1操作,dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER)为设置等待时间,这⾥设置的等待时间是⼀直等待。创建semaphore为0,等待,等10个⽹络请求都完成了,dispatch_semaphore_signal(semaphore)为计数+1,然后计数-1返回NSString*str=@"/";NSURL*url=[NSURL URLWithString:str];NSURLRequest*request=[NSURLRequest requestWithURL:url];NSURLSession*session=[NSURLSession sharedSession];dispatch_semaphore_t sem=dispatch_semaphore_create(0);for(inti=0;i<10;i++){NSURLSessionDataTask*task=[session dataTaskWithRequest:request completionHandler:^(NSData*_Nullabledata,NSURLResponse*_Nullable response,NSError*_Nullable error){NSLog(@"%d---%d",i,i);count++;if(count==10){dispatch_semaphore_signal(sem);count=0;}}];[task resume];}dispatch_semaphore_wait(sem,DISPATCH_TIME_FOREVER);dispatch_async(dispatch_get_main_queue(),^{NSLog(@"end");});7.多个⽹络请求顺序执⾏后如何执⾏下⼀步?使⽤信号量semaphore每⼀次遍历,都让其dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER),这个时候线程会等待,阻塞当前线程,直到dispatch_semaphore_signal(sem)调⽤之后NSString*str=@"/p/6930f335adba";NSURL*url=[NSURL URLWithString:str];NSURLRequest*request=[NSURLRequest requestWithURL:url];NSURLSession*session=[NSURLSession sharedSession];dispatch_semaphore_t sem=dispatch_semaphore_create(0);for(inti=0;i<10;i++){NSURLSessionDataTask*task=[session dataTaskWithRequest:request completionHandler:^(NSData*_Nullabledata,NSURLResponse*_Nullable response,NSError*_Nullable error){NSLog(@"%d---%d",i,i);dispatch_semaphore_signal(sem);}];[task resume];dispatch_semaphore_wait(sem,DISPATCH_TIME_FOREVER);}dispatch_async(dispatch_get_main_queue(),^{NSLog(@"end");});8.如何理解多线程中的死锁?死锁是由于多个线程(进程)在执⾏过程中,因为争夺资源⽽造成的互相等待现象,你可以理解为卡主了。产⽣死锁的必要条件有四个:互斥条件 :指进程对所分配到的资源进⾏排它性使⽤,即在⼀段时间内某资源只由⼀个进程占⽤。如果此时还有其它进程请求资源,则请求者只能等待,直⾄占有资源的进程⽤毕释放。请求和保持条件 :指进程已经保持⾄少⼀个资源,但⼜提出了新的资源请求,⽽该资源已被其它进程占有,此时请求进程阻塞,但⼜对⾃⼰已获得的其它资源保持不放。不可剥夺条件 :指进程已获得的资源,在未使⽤完之前,不能被剥夺,只能在使⽤完时由⾃⼰释放。环路等待条件 :指在发⽣死锁时,必然存在⼀个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待⼀个P1占⽤的资源;P1正在等待P2占⽤的资源,……,Pn正在等待已被P0占⽤的资源。最常见的就是 同步函数 + 主队列 的组合,本质是队列阻塞。dispatch_sync(dispatch_get_main_queue(),^{NSLog(@"2");});NSLog(@"1");// 什么也不会打印,直接报错9.如何去理解GCD执⾏原理?GCD有⼀个底层线程池,这个池中存放的是⼀个个的线程。之所以称为“池”,很容易理解出这个“池”中的线程是可以重⽤的,当⼀段时间后这个线程没有被调⽤胡话,这个线程就会被销毁。注意:开多少条线程是由底层线程池决定的(线程建议控制再3~5条),池是系统⾃动来维护,不需要我们程序员来维护(看到这句话是不是很开⼼?) ⽽我们程序员需要关⼼的是什么呢?我们只关⼼的是向队列中添加任务,队列调度即可。如果队列中存放的是同步任务,则任务出队后,底层线程池中会提供⼀条线程供这个任务执⾏,任务执⾏完毕后这条线程再回到线程池。这样队列中的任务反复调度,因为是同步的,所以当我们⽤currentThread打印的时候,就是同⼀条线程。如果队列中存放的是异步的任务,(注意异步可以开线程),当任务出队后,底层线程池会提供⼀个线程供任务执⾏,因为是异步执⾏,队列中的任务不需等待当前任务执⾏完毕就可以调度下⼀个任务,这时底层线程池中会再次提供⼀个线程供第⼆个任务执⾏,执⾏完毕后再回到底层线程池中。这样就对线程完成⼀个复⽤,⽽不需要每⼀个任务执⾏都开启新的线程,也就从⽽节约的系统的开销,提⾼了效率。在iOS7.0的时候,使⽤GCD系统通常只能开58条线程,iOS8.0以后,系统可以开启很多条线程,但是实在开发应⽤中,建议开启线程条数:35条最为合理。

发布者:admin,转转请注明出处:http://www.yc00.com/news/1690835621a441355.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信