zoukankan      html  css  js  c++  java
  • iOS-多线程--介绍NSThread和GCD及其它们的线程通讯示例

    前言:下面就不一一列出 pthread、NSThread、GCD、NSOperation 的完整的各种方法了,只分别将最常用的列出来,以便偶尔瞄一眼。


    一、NSThread

    1> 线程间的通讯
    /** 这个例子为在创建的子线程中下载图片,然后回到主线程中设置图片 ( 更新UI ) */
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    }

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        // 隐式创建并启动线程
        [self performSelectorInBackground:@selector(download) withObject:nil];
    }

    /**
     *  图片下载
     */
    - (void)download
    {
        NSLog(@"download---%@", [NSThread currentThread]);
        // 1.图片地址
        NSString *urlStr = @"http://d.hiphotos.baidu.com/image/pic/item/37d3d539b6003af3290eaf5d362ac65c1038b652.jpg";
        NSURL *url = [NSURL URLWithString:urlStr];
        
        // 2.根据地址下载图片的二进制数据(耗时的代码)
        NSLog(@"---begin");
        NSData *data = [NSData dataWithContentsOfURL:url];
        NSLog(@"---end");
        
        // 3.设置图片
        UIImage *image = [UIImage imageWithData:data];
        
        // 4.回到主线程,刷新UI界面(为了线程安全)
        [self performSelectorOnMainThread:@selector(downloadFinished:) withObject:image waitUntilDone:NO];
    //    [self performSelector:@selector(downloadFinished:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES];
    //    [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];
        
        NSLog(@"-----over----");
    }

    - (void)downloadFinished:(UIImage *)image
    {
        self.imageView.image = image;
        
        NSLog(@"downloadFinished---%@", [NSThread currentThread]);
    }
    @end
    /****************************分割线****************************/





    、GCD

    1> 、GCD    【 (任务)同步/异步***(队列)串行/并发*****任务和队列的几种组合方式 】
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    }

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        [self asyncSerialQueue];
    }


    // 就下面三个最常用,(GCD中其他情况不要管)
    /**

     * 第一种组合方式
     *  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]);
        });
    }
    /**
     *第一种组合方式 打印结果
     2016-04-07 17:48:05.007 Test-GCD测试一下[909:50754] -----下载图片2---<NSThread: 0x7f8acb50ea50>{number = 3, name = (null)}
     2016-04-07 17:48:05.007 Test-GCD测试一下[909:50755] -----下载图片1---<NSThread: 0x7f8acb4bedf0>{number = 2, name = (null)}
     2016-04-07 17:48:05.007 Test-GCD测试一下[909:50762] -----下载图片4---<NSThread: 0x7f8acb71b570>{number = 5, name = (null)}
     2016-04-07 17:48:05.007 Test-GCD测试一下[909:50763] -----下载图片5---<NSThread: 0x7f8acb510160>{number = 6, name = (null)}
     2016-04-07 17:48:05.007 Test-GCD测试一下[909:50758] -----下载图片3---<NSThread: 0x7f8acb60e780>{number = 4, name = (null)}
     */


    /** 

     * 第二种组合方式
     *  async -- 串行队列(有时候用)
     *  会不会创建线程:会,一般只开1条线程
     *  任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
     */
    - (void)asyncSerialQueue
    {
        // 1.创建一个串行队列
        dispatch_queue_t queue = dispatch_queue_create("cn.heima.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);
    }

    /**

     * 第二种方式 打印结果
     2016-04-07 17:49:33.730 Test-GCD测试一下[921:52233] -----下载图片1---<NSThread: 0x7f926ad09e20>{number = 2, name = (null)}
     2016-04-07 17:49:33.731 Test-GCD测试一下[921:52233] -----下载图片2---<NSThread: 0x7f926ad09e20>{number = 2, name = (null)}
     2016-04-07 17:49:33.731 Test-GCD测试一下[921:52233] -----下载图片3---<NSThread: 0x7f926ad09e20>{number = 2, name = (null)}
     2016-04-07 17:49:33.731 Test-GCD测试一下[921:52233] -----下载图片4---<NSThread: 0x7f926ad09e20>{number = 2, name = (null)}
     2016-04-07 17:49:33.731 Test-GCD测试一下[921:52233] -----下载图片5---<NSThread: 0x7f926ad09e20>{number = 2, name = (null)}
     */



    /**

     * 第三种方式 (这是一种特殊的方式,将 任务 添加到主队列中 异步 执行)
     *  async -- 主队列(很常用)     (一般在线程之间的通讯才用得上 @xz)
     */
    - (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]);
        });
    }

    /**

     * 第三种方式 打印结果如下

    2016-04-07 16:50:04.245 Test-GCD测试一下[801:31778] -----下载图片1---<NSThread: 0x7fb2a2d0a1e0>{number = 1, name = main}
    2016-04-07 16:50:04.246 Test-GCD测试一下[801:31778] -----下载图片2---<NSThread: 0x7fb2a2d0a1e0>{number = 1, name = main}
    2016-04-07 16:50:04.246 Test-GCD测试一下[801:31778] -----下载图片3---<NSThread: 0x7fb2a2d0a1e0>{number = 1, name = main}
    2016-04-07 16:50:04.247 Test-GCD测试一下[801:31778] -----下载图片4---<NSThread: 0x7fb2a2d0a1e0>{number = 1, name = main}
    2016-04-07 16:50:04.248 Test-GCD测试一下[801:31778] -----下载图片5---<NSThread: 0x7fb2a2d0a1e0>{number = 1, name = main}

    */



    2> GCD------线程间通讯示例

    注意点:
    <1>.  需要设置按钮的image和backgroundImage,建议先把按钮类型改为custom,才能保证设置成功
    <2>.  属性名不能以new开头
    <3>.  只有在init开头的构造方法中,才允许对self进行赋值

    #define XZGlobalQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
    #define XZMainQueue dispatch_get_main_queue()

    #import "XZViewController.h"

    @interface XZViewController ()
    @property (weak, nonatomic) IBOutlet UIButton *button;
    @end

    @implementation XZViewController

    - (void)viewDidLoad
    {
        [super viewDidLoad];
    }

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {

            UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(20, 20, 100, 60)];
            [self.view addSubview:button];
            self.button = button;


            dispatch_async(XZGlobalQueue, ^{
            NSLog(@"donwload---%@", [NSThread currentThread]);
            // 1.子线程下载图片
            NSURL *url = [NSURL URLWithString:@"http://d.hiphotos.baidu.com/image/pic/item/37d3d539b6003af3290eaf5d362ac65c1038b652.jpg"];
            NSData *data = [NSData dataWithContentsOfURL:url];
            UIImage *image = [UIImage imageWithData:data];
            
            // 2.回到主线程设置图片
            dispatch_async(XZMainQueue, ^{
                NSLog(@"setting---%@ %@", [NSThread currentThread], image);
                [self.button setImage:image forState:UIControlStateNormal];
            });
        });
    }

    @end

    /*

     * 打印结果

    Test-GCD测试一下[873:44012] donwload---<NSThread: 0x7fc7a0401d50>{number = 2, name = (null)}
    Test-GCD测试一下[873:43920] setting---<NSThread: 0x7fc7a0507930>{number = 1, name = main} <UIImage: 0x7fc7a0681530>, {440, 608}

     */
    /****************************分割线****************************/

  • 相关阅读:
    【Todo】各种语言里面的for循环 & loop
    git/icode操作记录
    UVA 639 (13.08.25)
    TkinterGUI
    [置顶] think in java interview-高级开发人员面试宝典(七)
    通过memcached来实现对tomcat集群中Session的共享策略
    Hibernate 配置详解(7)
    python模块之bsddb: bdb高性能嵌入式数据库 1.基础知识
    Python基础
    Objective-C中NSArray和NSMutableArray的基本用法
  • 原文地址:https://www.cnblogs.com/nxz-diy/p/5364627.html
Copyright © 2011-2022 走看看