GCD多线程

        Grand Central Dispatch可以简化多线程编程。可以将应用程序需要执行的工作拆分为可分散在多个线程和多个cpu上更小的块。多线程还是得了解底层的实现,GCD只是进行了封装。

以下为实例:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
- (IBAction)doWork:(id)sender;
@property (weak, nonatomic) IBOutlet UITextView *resultsTextView;
@property (weak, nonatomic) IBOutlet UIButton *startButton;
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *spinner;

@end
//
//  ViewController.m
//  Study20130220
//
//  Created by Dwen on 13-2-20.
//  Copyright (c) 2013年 Dwen. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController
@synthesize startButton,resultsTextView,spinner;

- (void)viewDidLoad
{
    [super viewDidLoad];
	NSLog(@"load view...");
//    //定义程序块
//    void(^loggerBlock)(void);
//    //实现程序块
//    loggerBlock = ^{NSLog(@"i am test block.");};
//    //执行程序块
//    loggerBlock();
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (NSString *)fetchSomethingFromServer{
    [NSThread sleepForTimeInterval:1];
    return @"Hi there";
}

- (NSString *)processData:(NSString *)data{
    [NSThread sleepForTimeInterval:2];
    return [data uppercaseString];
}

- (NSString *)calculateFirstResult:(NSString *)data{
    [NSThread sleepForTimeInterval:3];
    return [NSString stringWithFormat:@"Number of chars: %d",[data length]];
}

- (NSString *)calculateSecondResult:(NSString *)data{
    [NSThread sleepForTimeInterval:4];
    return [data stringByReplacingOccurrencesOfString:@"E" withString:@"e"];
}

- (IBAction)doWork:(id)sender {
    //并发程序块
    startButton.enabled = NO;
    startButton.alpha = 0.5;
    [spinner startAnimating];
    NSDate *startTime = [NSDate date];
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSString *fetchedData = [self fetchSomethingFromServer];
        NSString *processData = [self processData:fetchedData];
        
        __block NSString *firstResult;
        __block NSString *secondResult;
        dispatch_group_t group = dispatch_group_create();
        dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
            NSLog(@"calculateFirstResult...");
            firstResult = [self calculateFirstResult:processData];
        });
        dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
            NSLog(@"calculateSecondResult...");
            secondResult = [self calculateSecondResult:processData];
        });
        //dispatch_group_notify指定一个额外的程序块,该程序块将在组中的所有程序块运行完成时执行
        dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{
            NSString *resultsSummary = [NSString stringWithFormat:@"First: [%@]\nSecond: [%@]",firstResult,secondResult];
            NSLog(@"resultsSummary :%@",resultsSummary);
            //dispatch_get_main_queue主线程
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"change value.");
                startButton.enabled = YES;
                startButton.alpha = 1.0;
                [spinner stopAnimating];
                resultsTextView.text = resultsSummary;
            });
            NSDate *endTime = [NSDate date];
            NSLog(@"Completed in %f seconds",[endTime timeIntervalSinceDate:startTime]);
        });
    });
    
    //异步执行
//    startButton.enabled = NO;
//    startButton.alpha = 0.5;
//    [spinner startAnimating];
//    NSDate *startTime = [NSDate date];
//    dispatch_async(dispatch_get_global_queue(0, 0), ^{
//        NSString *fetchedData = [self fetchSomethingFromServer];
//        NSString *processData = [self processData:fetchedData];
//        NSString *firstResult = [self calculateFirstResult:processData];
//        NSString *secondResult = [self calculateSecondResult:processData];
//        NSString *resultsSummary = [NSString stringWithFormat:@"First: [%@]\nSecond: [%@]",firstResult,secondResult];
//        NSLog(@"resultsSummary :%@",resultsSummary);
//        dispatch_async(dispatch_get_main_queue(), ^{
//            NSLog(@"change value.");
//            startButton.enabled = YES;
//            startButton.alpha = 1.0;
//            [spinner stopAnimating];
//            resultsTextView.text = resultsSummary;
//        });
//        NSDate *endTime = [NSDate date];
//        NSLog(@"Completed in %f seconds",[endTime timeIntervalSinceDate:startTime]);
//    });
    
    //同步执行
//    NSDate *startTime = [NSDate date];
//    NSString *fetchedData = [self fetchSomethingFromServer];
//    NSString *processData = [self processData:fetchedData];
//    NSString *firstResult = [self calculateFirstResult:processData];
//    NSString *secondResult = [self calculateSecondResult:processData];
//    NSString *resultsSummary = [NSString stringWithFormat:@"First: [%@]\nSecond: [%@]",firstResult,secondResult];
//    resultsTextView.text = resultsSummary;
//    NSDate *endTime = [NSDate date];
//    NSLog(@"Completed in %f seconds",[endTime timeIntervalSinceDate:startTime]);
}
@end

异步执行需花10秒,而并发程序块只花了7秒,大大提高了效率。在真实的应用程序中,加速程度将取决于所执行的工作和可用的资源。只有在多个cpu核心可用时,执行cpu资源密集型的计算才能受益于此技术。

=================================================================================

NSThread和GCD是多线程的两种实现方式,NSThread实现起来比GCD稍微复杂些,GCD要比较简单些,GCD是C语言提供的API。GCD支持多核CPU处理。

在GCD中,有3种类型的派发队列:

    1、串行队列。串行队列通常用于同步访问一个特定的资源,每次只能执行一个任务。使用函数dispatch_queue_create,可以创建串行队列。

    2、并发队列。也叫全局派发队列,可以并发地执行一个或多个任务。并发队列分为高、中、低3个优先级队列,中级为默认级别。可以使用调用dispatch_get_global_queue函数设定优先级来访问队列。

扫描二维码关注公众号,回复: 652183 查看本文章

    3、主队列。它在应用程序的主线程中,用于更新UI。使用dispatch_get_main_queue函数,可以获得主队列。

以下两种图片下载方式,效率完全不一样。

同步下载图片:

NSString *picPath = [NSString stringWithFormat:@"%@?imageView2/0/w/%d",_mdExhibitVo.exhibitPic,(int)(([UIScreen mainScreen].bounds.size.width-8*2)*2)];
    picPath = [picPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSData * picData = [NSData dataWithContentsOfURL:[NSURL URLWithString:picPath]];
self.imageView.image = [UIImage imageWithData:picData]];

异步下载图片:

NSString *smallImgStr = [NSString stringWithFormat:@"%@?imageView/0/w/200/q/20",_mdExhibitWorkVo.worksPic];
        smallImgStr = [smallImgStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        dispatch_queue_t downloadQueue = dispatch_queue_create("com.test.works.image", NULL);
        dispatch_async(downloadQueue, ^{
            NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:smallImgStr]];
            UIImage *img = [UIImage imageWithData:imgData];
            dispatch_async(dispatch_get_main_queue(), ^{
                _headerImageView.image = img;
                [[ImageProgressView sharedASIImageViewAppearance] setPlaceholderImage:img];
            });
        });

猜你喜欢

转载自wenxin2009.iteye.com/blog/1809855
今日推荐