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}

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

posted @ 2016-04-07 17:47  nxz_diy  阅读(279)  评论(0编辑  收藏  举报