• 转 多线程补充


    进程和线程

     
    要使用多线程,首先需要理解进程和线程这2个概念。这里我简单的说一下。
     
    所谓进程对应的是一个应用程序,负责开辟内存空间供应用程序使用,但是进程不能执行任务(指令)。一个进程至少包含一条线程,线程是程序的执行流。
     
    •iOS程序启动时,在创建一个进程的同时, 会开始运行一个线程,该线程被称为主线程
    系统中的每一个进程都有自己独立的虚拟内存空间,而同一个进程中的多个线程则共用进程的内存空间
    •每创建一个新的线程,都会消耗一定内存和CPU时间
    •当多个线程对同一个资源出现争夺的时候需要注意线程安全问题
     
    多线程的应用及使用注意事项
    将耗时、轮询或者并发需求高等任务分配到其他线程执行,并由主线程负责统一更新界面会使得应用程序更加流畅,用户体验更好,例如网络请求,播放游戏的背景音乐等。
    •线程使用不是无节制的
    –iOS中的主线程的堆栈大小是1M
    –从第二个线程开始都是512KB
    –这些数值不能通过编译器开关或线程API函数更改
    注:更新UI界面,处理界面和用户之间的交互事件一定要在主线程中处理。
     
    iOS中的多线程技术
     
    1.NSObject的多线程方法-对NSThread的封装(一个NSThread对象对应一条线程)
     
    •开启后台线程执行任务的方法
    -(void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg
    •在后台线程中通知主线程执行任务的方法
    –(void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
    •获取线程信息
    [NSThread currentThread];
    •线程休眠      
    [NSThread sleepForTimeInterval:1.0f];
    提示:
    –performSelectorInBackground方法本身是在主线程中执行的,而选择器指定的方法是在后台线程中进行的
    –尽管使用performSelectorInBackground方法调用的任务可以更新UI界面,但是在实际开发中,涉及到UI界面的更新操作,还是要使用performSelectorOnMainThread方法,以避免不必要的麻烦
    注:
    •内存管理对于多线程非常重要
    •Objective-C可以凭借@autoreleasepool使用内存资源,并需要时回收资源
    •每个线程都需要有@autoreleasepool,否则可能会出现内存泄漏
     
    2.NSThread
     
    •创建线程方法:
    1.+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;
    2.- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument;
    •参数说明:
    –selector:线程执行的方法,只能有一个参数,不能有返回值
    –target:selector消息发送的对象
    –argument:传输给target的唯一参数,也可以是nil
     
    3.NSOperation/NSOperationQueue
     
    •NSOperation的两个子类
    1.NSInvocationOperation
    2.NSBlockOperation
     
    •工作原理:
    1.用NSOperation封装要执行的操作
    2.将创建好的NSOperation对象放NSOperationQueue中
    3.启动OperationQueue开始新的线程执行队列中的操作
    •注意事项:
    1.使用多线程时通常需要控制线程的并发数,因为线程会消耗系统资源,同时运行的线程过多,系统会变慢
    2.使用以下方法可以控制并发的线程数量:
    -(void)setMaxConcurrentOperationCount:(NSInteger)cnt;
    3.使用addDependency可以建立操作之间的依赖关系,设定操作的执行顺序
     
     
    上面的程序设置依赖关系后,只有等操作a和b都执行完,才会执行c.
     
    4.GCD
     
    •GCD队列:
    1.全局队列:所有添加到主队列中的任务都是并发执行的(可能会开启多条线程)
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    2.串行队列:所有添加到串行队列中的任务都是顺序执行的(只可能会开启一条线程)
    dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
    3.主队列:所有添加到主队列中的任务都是在主线程中执行的
    dispatch_get_main_queue();
     
    •异步操作
    –dispatch_async 在其他线程执行任务,会开启新的线程
    –异步方法无法确定任务的执行顺序
    •同步操作
    –dispatch_sync 在当前在线程执行任务,不开启新的线程
    –同步操作与队列无关
    –同步方法会依次执行,能够决定任务的执行顺序
    –更新界面UI时,最好使用同步方法
    注:同步还是异步,取决于方法名(不影响主队列,影响全局队列、串行队列)。
  • 相关阅读:
    剑指Offer:面试题17——合并两个排序的链表
    剑指Offer:面试题16——反转链表(java实现)
    剑指Offer:面试题15——链表中倒数第k个结点(java实现)
    Timer和TimerTask 定时器和定时任务
    Spring-WebSocket 教程
    单点登录原理与简单实现
    Python机器学习:泰坦尼克号获救预测一
    转 smarty学习笔记电子版整理
    转 nodejs socket.io初探
    html5新增的属性和废除的属性
  • 原文地址:https://www.cnblogs.com/xlp724619666/p/4286276.html
Copyright © 2020-2023  润新知