美文网首页多线程开发
多线程pthread、NSThread和GCD的实现

多线程pthread、NSThread和GCD的实现

作者: Andy_Livings | 来源:发表于2020-04-15 15:47 被阅读0次

    一、pthread

    首先,导入#import <pthread.h>框架,然后再创建线程

    pthread_t myRestrict;
    pthread_create(&myRestrict, NULL, run, NULL);
    

    函数方法实现

    void *run(void *data) {
        
        for (NSInteger i = 0; i < 10000; i++) {
            NSLog(@"touchesBegan----%ld-----%@", i, [NSThread currentThread]);
        }
        return NULL;
    }
    

    二、NSThread

    创建线程的方式一

    /// 创建线程的方式1
    - (void)createThread1 {
        
        // 创建线程
        NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(downloadWithUrlString:) object:@"http://b.png"];
        thread.name = @"下载线程";
        
        // 启动线程(调用self的downloadWithUrlString方法)
        [thread start];
    }
    

    创建线程的方式二

    /// 创建线程的方式2
    - (void)createThread2 {
        
    //    [NSThread detachNewThreadWithBlock:^{
    //
    //        NSLog(@"---%@---", [NSThread currentThread]);
    //    }];
        [NSThread detachNewThreadSelector:@selector(downloadWithUrlString:) toTarget:self withObject:@"http://b.png"];
    }
    

    创建线程的方式三

    /// 创建线程的方式3
    - (void)createThread3 {
        
        // 这两个不会创建线程,只在当前线程中执行
    //    [self performSelector:@selector(downloadWithUrlString:) withObject:@"http://c.gif"];
    //    [self downloadWithUrlString:@"http://c.gif"];
    
        [self performSelectorInBackground:@selector(downloadWithUrlString:) withObject:@"http://c.gif"];
    }
    

    函数实现

    - (void)downloadWithUrlString:(NSString *)urlString {
        
        NSLog(@"download---%@---%@", urlString, [NSThread currentThread]);
    }
    

    三、GCD

    dispatch_sync : 同步,不具备开启线程的能力
    dispatch_async : 异步,具备开启线程的能力

    并发队列 :多个任务可以同时执行
    串行队列 :一个任务执行完后,再执行下一个任务

    Foundation : OC
    Core Foundation : C语言
    Foundation和Core Foundation框架的数据类型可以互相转换的

     NSString *str = @"123"; // Foundation
     CFStringRef str2 = (__bridge CFStringRef)str; // Core Foundation
     NSString *str3 = (__bridge NSString *)str2;
         CFArrayRef ---- NSArray
         CFDictionaryRef ---- NSDictionary
         CFNumberRef ---- NSNumber
    

    Core Foundation中手动创建的数据类型,都需要手动释放

         CFArrayRef array = CFArrayCreate(NULL, NULL, 10, NULL);
         CFRelease(array);
    
         CGPathRef path = CGPathCreateMutable();
         CGPathRetain(path);
    
         CGPathRelease(path);
         CGPathRelease(path);
    

    凡是函数名中带有create\copy\new\retain等字眼, 都应该在不需要使用这个数据的时候进行release
    GCD的数据类型在ARC环境下不需要再做release
    CF(Core Foundation)的数据类型在ARC\MRC环境下都需要再做release

    1、async -- 并发队列(最常用)
    /**
     *  async -- 并发队列(最常用)
     *  会不会创建线程:会,一般同时开多条
     *  任务的执行方式:并发执行
     */
    - (void)asyncGlobalQueue {
        
        // 获得全局的并发队列
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        
        // 将 任务 添加 全局队列 中去 异步 执行
        dispatch_async(queue, ^{
            NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
        });
    }
    
    2、async -- 串行队列(有时候用)
    /**
     *  async -- 串行队列(有时候用)
     *  会不会创建线程:会,一般只开1条线程
     *  任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
     */
    - (void)asyncSerialQueue {
        
        // 1.创建一个串行队列
        dispatch_queue_t queue = dispatch_queue_create("com.asliving.queue", NULL);
        
        // 2.将任务添加到串行队列中 异步 执行
        dispatch_async(queue, ^{
            NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
        });
        
        // 3.非ARC,需要释放创建的队列
        //    dispatch_release(queue);
    }
    
    3、async -- 主队列(很常用)
    /**
     *  async -- 主队列(很常用)
     */
    - (void)asyncMainQueue {
        
        // 1.主队列(添加到主队列中的任务,都会自动放到主线程中去执行)
        dispatch_queue_t queue = dispatch_get_main_queue();
        
        // 2.添加 任务 到主队列中 异步 执行
        dispatch_async(queue, ^{
            NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
        });
    }
    
    4、sync -- 主队列(不能用---会卡死)
    /**
     *  sync -- 主队列(不能用---会卡死)
     */
    - (void)syncMainQueue {
        
        NSLog(@"syncMainQueue----begin--");
        
        // 1.主队列(添加到主队列中的任务,都会自动放到主线程中去执行)
        dispatch_queue_t queue = dispatch_get_main_queue();
        
        // 2.添加 任务 到主队列中 异步 执行
        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
        });
        
        NSLog(@"syncMainQueue----end--");
    }
    

    -----------------------------华丽的分割线------------------------------

    5、sync -- 并发队列
    /**
     *  sync -- 并发队列
     *  会不会创建线程:不会
     *  任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
     *  并发队列失去了并发的功能
     */
    - (void)syncGlobalQueue {
        
        // 获得全局的并发队列
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        
        // 将 任务 添加到 全局并发队列 中 同步 执行
        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
        });
    }
    
    6、sync -- 串行队列
    /**
     *  sync -- 串行队列
     *  会不会创建线程:不会
     *  任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
     */
    - (void)syncSerialQueue {
        
        // 创建一个串行队列
        dispatch_queue_t queue = dispatch_queue_create("cn.heima.queue", NULL);
        
        // 将 任务 添加到 串行队列 中 同步 执行
        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
        });
    }
    

    Demo地址

    相关文章

      网友评论

        本文标题:多线程pthread、NSThread和GCD的实现

        本文链接:https://www.haomeiwen.com/subject/vvtcvhtx.html