博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
多线程开发之三 GCD
阅读量:7051 次
发布时间:2019-06-28

本文共 25395 字,大约阅读时间需要 84 分钟。

NSThread、NSOperation、GCD 总结:

  1. 无论使用哪种方法进行多线程开发,每个线程启动后并不一定立即执行相应的操作,具体什么时候由系统调度(CPU 空闲时就会执行)

  2. 更新 UI 应该在主线程(UI 线程)中进行,并且推荐使用异步调用,避免造成线程阻塞,常用的方法如下:

    - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;

    - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL) wait; //方法传递主线程[NSThread mainThread])

    [NSOperationQueue mainQueue] addOperationWithBlock:

    dispatch_async(dispatch_get_main_queue(), ^{}) //在主线程中,这里改用同步调用 dispatch_sync 的话就会造成线程阻塞情况 

  3. NSThread 适合轻量级多线程开发,控制线程顺序比较难,同时线程总数无法控制(每次创建并不能重用之前的线程,只能创建一个新的线程)

  4. 对于简单的多线程开发建议使用 NSObject 的扩展方法完成,而不必使用 NSThread

  5. 可以使用 NSThread 的 currentThread 方法取得当前线程,使用 sleepForTimeInterval: 方法让当前线程挂起

  6. NSOperation 进行多线程开发可以控制线程总数及线程依赖关系

  7. 创建一个 NSOperation 不应该直接调用 start 方法(如果直接 start 则会在主线程中调用)而是应该放到 NSOperationQueue 中启动

  8. 相比 NSInvocationOperation 推荐使用 NSBlockOperation,代码简单,同时由于闭包性使他没有传参问题

  9. NSOperation 是对 GCD 面向对象的 OC 封装。而 GCD 基于 C 语言开发,效率更高。建议如果任务之间有依赖关系或者想要监听任务完成状态的情况下优先选择 NSOperation,否则使用 GCD

  10. 在 GCD 中串行队列中的任务被安排到一个单一线程执行(不是主线程),可以方便地控制执行顺序;并发队列在多个线程中执行(前提是使用异步方法),顺序控制相对复杂,但是更高效

  11. 在 GCD 中一个操作是多线程还是单线程执行,取决于当前队列类型和执行方法。只有队列类型为并行队列并且使用异步方法执行时才能在多个线程中执行(如果是并行队列使用同步方法调用则会在主线程中执行)

 

效果如下:

 

ViewController.h

1 #import 
2 3 @interface ViewController : UITableViewController4 @property (copy, nonatomic) NSArray *arrSampleName;5 6 - (instancetype)initWithSampleNameArray:(NSArray *)arrSampleName;7 8 @end

ViewController.m

1 #import "ViewController.h" 2 #import "FirstSampleViewController.h" 3 #import "SecondSampleViewController.h" 4  5 @interface ViewController () 6 - (void)layoutUI; 7 @end 8  9 @implementation ViewController10 - (void)viewDidLoad {11     [super viewDidLoad];12     13     [self layoutUI];14 }15 16 - (void)didReceiveMemoryWarning {17     [super didReceiveMemoryWarning];18     // Dispose of any resources that can be recreated.19 }20 21 - (instancetype)initWithSampleNameArray:(NSArray *)arrSampleName {22     if (self = [super initWithStyle:UITableViewStyleGrouped]) {23         self.navigationItem.title = @"多线程开发之三 GCD";24         self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"返回首页" style:UIBarButtonItemStylePlain target:nil action:nil];25         26         _arrSampleName = arrSampleName;27     }28     return self;29 }30 31 - (void)layoutUI {32 }33 34 #pragma mark - UITableViewController相关方法重写35 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {36     return 0.1;37 }38 39 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {40     return 1;41 }42 43 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {44     return [_arrSampleName count];45 }46 47 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {48     static NSString *cellIdentifier = @"cell";49     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];50     if (!cell) {51         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];52     }53     cell.textLabel.text = _arrSampleName[indexPath.row];54     return cell;55 }56 57 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {58     switch (indexPath.row) {59         case 0: {60             FirstSampleViewController *firstSampleVC = [FirstSampleViewController new];61             [self.navigationController pushViewController:firstSampleVC animated:YES];62             break;63         }64         case 1: {65             SecondSampleViewController *secondSampleVC = [SecondSampleViewController new];66             [self.navigationController pushViewController:secondSampleVC animated:YES];67             break;68         }69         default:70             break;71     }72 }73 74 @end

UIImage+RescaleImage.h

1 #import 
2 3 @interface UIImage (RescaleImage) 4 /** 5 * 根据宽高大小,获取对应的缩放图片 6 * 7 * @param size 宽高大小 8 * 9 * @return 对应的缩放图片10 */11 - (UIImage *)rescaleImageToSize:(CGSize)size;12 13 @end 

UIImage+RescaleImage.m

1 #import "UIImage+RescaleImage.h" 2  3 @implementation UIImage (RescaleImage) 4  5 - (UIImage *)rescaleImageToSize:(CGSize)size { 6     CGRect rect = CGRectMake(0.0, 0.0, size.width, size.height); 7      8     UIGraphicsBeginImageContext(rect.size); 9     [self drawInRect:rect];10     UIImage *imgScale = UIGraphicsGetImageFromCurrentImageContext();11     UIGraphicsEndImageContext();12     13     return imgScale;14 }15 16 @end

Common.h

1 #import 
2 3 @interface Common : NSObject4 + (NSURL *)randomImageURL;5 6 @end 

Common.m

1 #import "Common.h" 2  3 static NSArray *arrPartOfURL = nil; 4 @implementation Common 5  6 + (NSURL *)randomImageURL { 7     if (arrPartOfURL == nil) { 8         arrPartOfURL = @[ 9                          @"chronograph",10                          @"color",11                          @"modular",12                          @"utility",13                          @"mickey_mouse",14                          @"simple",15                          @"motion",16                          @"solar",17                          @"astronomy",18                          @"timer",19                          @"alarm",20                          @"world_clock"21                          ];22     }23     24     NSUInteger randomVal = (arc4random() % 12); //0-11的随机数25     NSString *imageURLStr = [NSString stringWithFormat:@"http://images.apple.com/v/watch/e/timekeeping/images/%@_large.jpg", arrPartOfURL[randomVal]];26     return [NSURL URLWithString:imageURLStr];27 }28 29 @end 

FirstSampleViewController.h

1 #import 
2 3 @interface FirstSampleViewController : UIViewController4 @property (assign, nonatomic) CGSize rescaleImageSize;5 6 @property (strong, nonatomic) IBOutlet UIImageView *imgV;7 @property (strong, nonatomic) IBOutlet UIButton *btnLoadImage;8 9 @end 

FirstSampleViewController.m

1 #import "FirstSampleViewController.h"  2 #import "UIImage+RescaleImage.h"  3 #import "Common.h"  4   5 @interface FirstSampleViewController ()  6 - (void)layoutUI;  7 - (void)updateImage:(NSData *)imageData;  8 @end  9  10 @implementation FirstSampleViewController 11  12 - (void)viewDidLoad { 13     [super viewDidLoad]; 14      15     [self layoutUI]; 16 } 17  18 - (void)didReceiveMemoryWarning { 19     [super didReceiveMemoryWarning]; 20     // Dispose of any resources that can be recreated. 21 } 22  23 - (void)dealloc { 24     _imgV.image = nil; 25 } 26  27 - (void)layoutUI { 28     self.view.backgroundColor = [UIColor colorWithWhite:0.957 alpha:1.000]; 29      30     CGFloat width = [[UIScreen mainScreen] bounds].size.width; //bounds 返回整个屏幕大小;applicationFrame 返回去除状态栏后的屏幕大小 31     CGFloat height = width * 243.0 / 221.0; 32     const CGFloat percentVal = 3.0 / 4.0; //以屏幕宽度的3/4比例显示 33     _rescaleImageSize = CGSizeMake(width * percentVal, height * percentVal); 34      35     //NSString *path = [[NSBundle mainBundle] pathForResource:@"PictureNo@2x" ofType:@"png"]; 36     //_imgV.image = [UIImage imageWithContentsOfFile:path]; 37      38     _btnLoadImage.tintColor = [UIColor darkGrayColor]; 39     _btnLoadImage.layer.masksToBounds = YES; 40     _btnLoadImage.layer.cornerRadius = 10.0; 41     _btnLoadImage.layer.borderColor = [UIColor grayColor].CGColor; 42     _btnLoadImage.layer.borderWidth = 1.0; 43 } 44  45 - (void)updateImage:(NSData *)imageData { 46     UIImage *img = [UIImage imageWithData:imageData]; 47     _imgV.image = [img rescaleImageToSize:_rescaleImageSize]; 48 } 49  50 - (IBAction)loadImage:(id)sender { 51     /* 52      GCD(Grand Central Dispatch):中央调度 53      相比 NSThread 和 NSOperation 来说,他的显著优点是:对于多核运算更加有效 54      1、GCD 的一个重要概念是队列,他的核心理念:将多个任务添加到 dispatch queue(调度队列)中,系统会为我们管理这些 dispath queue,为我们在多个线程上分配并执行任务,我们不需要直接启动和管理后台线程。 55      2、系统提供了许多预定义的 dispatch queue,包括可以保证始终在主线程上执行工作的 dispatch queue。也可以创建自己的dispatch queue,而且可以创建任意多个。GCD的 dispatch queue 严格遵循 FIFO(先进先出)原则,添加到 dispatch queue 的任务将始终按照加入 dispatch queue 的顺序启动。 56      3、dispatch queue按先进先出的顺序,串行或并发地执行任务 57      1> serial dispatch queue(串行调度队列):一次只能执行一个任务,当前任务完成后才开始出列并启动下一个任务 58      2> concurrent dispatch queue(并发调度队列):则尽可能多地启动任务并发执行 59       60      同步和异步决定了要不要开启新的线程 61      同步:在当前线程中执行任务,不具备开启新线程的能力(如果当前线程是主线程的话,会造成线程阻塞,一般比较少用) 62      异步:在新的线程中执行任务,具备开启新线程的能力 63       64      串行和并发决定了任务的执行方式 65      串行:一个任务执行完毕后,再执行下一个任务 66      并发:多个任务并发(同时)执行 67      */ 68      69     /* 70      系统给每个应用提供了四个全局并发队列,整个应用内全局共享,他们的区别是通过「全局并发队列优先级」;优先级越高,队列越先被列入执行计划中 71      #define DISPATCH_QUEUE_PRIORITY_HIGH 2 72      #define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 73      #define DISPATCH_QUEUE_PRIORITY_LOW (-2) 74      #define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN 75      */ 76      77     //全局并发队列 78     dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 79      80     //自定义串行队列;第二个参数为 NULL 或 DISPATCH_QUEUE_SERIAL 表示串行队列,而为 DISPATCH_QUEUE_CONCURRENT 表示并发队列,但一般用 dispatch_get_global_queue 方法获取并发队列 81     //dispatch_queue_t customSerialQueue = dispatch_queue_create("Custom Queue", NULL); 82      83     //主队列;属于串行队列 84     dispatch_queue_t mainQueue = dispatch_get_main_queue(); 85      86      87     //方法一:自定义串行队列同步:不会开启新线程、串行执行任务 88 //    dispatch_sync(customSerialQueue, ^{ 89 //        NSLog(@"自定义串行队列同步,线程:%@", [NSThread currentThread]); //所在的线程,这里就是在主线程 90 //        NSURL *url = [Common randomImageURL]; 91 //        NSData *data = [NSData dataWithContentsOfURL:url]; 92 //         93 //        dispatch_async(mainQueue, ^{ //主队列异步(同步也一样):不会开启新线程、串行执行任务 94 //            NSLog(@"主队列异步(同步也一样),线程:%@", [NSThread currentThread]); //主队列所对应的主线程 95 //            [self updateImage:data]; 96 //        }); 97 //    }); 98      99     //方法二:自定义串行队列异步:开启新线程、串行执行任务100 //    dispatch_async(customSerialQueue, ^{101 //        NSLog(@"自定义串行队列异步,线程:%@", [NSThread currentThread]); //开启的新线程102 //        NSURL *url = [Common randomImageURL];103 //        NSData *data = [NSData dataWithContentsOfURL:url];104 //        105 //        dispatch_async(mainQueue, ^{ //主队列异步(同步也一样):不会开启新线程、串行执行任务106 //            NSLog(@"主队列异步(同步也一样),线程:%@", [NSThread currentThread]); //主队列所对应的主线程107 //            [self updateImage:data];108 //        });109 //    });110     111     112     //方法三:全局并发队列同步:不会开启新线程、串行执行任务113 //    dispatch_sync(globalQueue, ^{114 //        NSLog(@"全局并发队列同步,线程:%@", [NSThread currentThread]); //所在的线程,这里就是在主线程115 //        NSURL *url = [Common randomImageURL];116 //        NSData *data = [NSData dataWithContentsOfURL:url];117 //        118 //        dispatch_async(mainQueue, ^{ //主队列异步(同步也一样):不会开启新线程、串行执行任务119 //            NSLog(@"主队列异步(同步也一样),线程:%@", [NSThread currentThread]); //主队列所对应的主线程120 //            [self updateImage:data];121 //        });122 //    });123     124     125     //方法四:全局并发队列异步:开启新线程、并发执行任务126     dispatch_async(globalQueue, ^{127         NSLog(@"全局并发队列异步,线程:%@", [NSThread currentThread]); //开启的新线程128         NSURL *url = [Common randomImageURL];129         NSData *data = [NSData dataWithContentsOfURL:url];130         131         dispatch_async(mainQueue, ^{ //主队列异步(同步也一样):不会开启新线程、串行执行任务132             NSLog(@"主队列异步(同步也一样),线程:%@", [NSThread currentThread]); //主队列所对应的主线程133             [self updateImage:data];134         });135     });136 }137 138 @end 

FirstSampleViewController.xib

1 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
 

SecondSampleViewController.h

1 #import 
2 3 @interface SecondSampleViewController : UIViewController4 @property (assign, nonatomic) CGSize rescaleImageSize;5 @property (strong, nonatomic) NSMutableArray *mArrImageView;6 7 @property (strong, nonatomic) IBOutlet UIButton *btnLoadImage;8 9 @end 

SecondSampleViewController.m

1 #import "SecondSampleViewController.h"  2 #import "UIImage+RescaleImage.h"  3 #import "Common.h"  4   5 #define kRowCount 4  6 #define kColumnCount 3  7 #define kCellSpacing 10.0  8   9 @interface SecondSampleViewController () 10 - (void)layoutUI; 11 - (void)updateImage:(NSData *)imageData withImageIndex:(NSInteger)imageIndex; 12 -(NSData *)requestData:(NSInteger)imageIndex; 13 - (void)loadImageFromNetwork:(NSInteger)imageIndex; 14 - (void)loadImageByDispatchAsync; 15 - (void)loadImageByDispatchApply; 16 - (void)loadImageByDispatchGroupAsync; 17 - (void)additionalInfo; 18 @end 19  20 @implementation SecondSampleViewController 21  22 - (void)viewDidLoad { 23     [super viewDidLoad]; 24      25     [self layoutUI]; 26 } 27  28 - (void)didReceiveMemoryWarning { 29     [super didReceiveMemoryWarning]; 30     // Dispose of any resources that can be recreated. 31 } 32  33 - (void)dealloc { 34     _mArrImageView = nil; 35 } 36  37 - (void)layoutUI { 38     self.view.backgroundColor = [UIColor colorWithWhite:0.957 alpha:1.000]; 39      40     CGFloat width = ([[UIScreen mainScreen] bounds].size.width - ((kColumnCount + 1) * kCellSpacing)) / kColumnCount; 41     _rescaleImageSize = CGSizeMake(width, width); 42      43     CGFloat heightOfStatusAndNav = 20.0 + 44.0; 44     NSString *path = [[NSBundle mainBundle] pathForResource:@"PictureNo@2x" ofType:@"png"]; 45     UIImage *img = [UIImage imageWithContentsOfFile:path]; 46     _mArrImageView = [NSMutableArray arrayWithCapacity:kRowCount * kColumnCount]; 47     //初始化多个图片视图 48     for (NSUInteger i=0; i

SecondSampleViewController.xib

1 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
32
33
34
35
36
37
38
39
40
 

AppDelegate.h

1 #import 
2 3 @interface AppDelegate : UIResponder
4 5 @property (strong, nonatomic) UIWindow *window;6 @property (strong, nonatomic) UINavigationController *navigationController;7 8 @end 

AppDelegate.m

1 #import "AppDelegate.h" 2 #import "ViewController.h" 3  4 @interface AppDelegate () 5  6 @end 7  8 @implementation AppDelegate 9 10 11 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {12     _window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];13     ViewController *viewController = [[ViewController alloc] initWithSampleNameArray:@[@"请求单张网络图片(解决线程阻塞)", @"请求多张网络图片(多个线程并发)"]];14     _navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];15     _window.rootViewController = _navigationController;16     //[_window addSubview:_navigationController.view]; //当_window.rootViewController关联时,这一句可有可无17     [_window makeKeyAndVisible];18     return YES;19 }20 21 - (void)applicationWillResignActive:(UIApplication *)application {22 }23 24 - (void)applicationDidEnterBackground:(UIApplication *)application {25 }26 27 - (void)applicationWillEnterForeground:(UIApplication *)application {28 }29 30 - (void)applicationDidBecomeActive:(UIApplication *)application {31 }32 33 - (void)applicationWillTerminate:(UIApplication *)application {34 }35 36 @end 

输出结果:

方法三:dispatch_group_async

1 2015-08-30 17:19:44.168 GCDDemo[4776:70114] 全局并发队列异步,线程:
{number = 4, name = (null)} 2 2015-08-30 17:19:44.168 GCDDemo[4776:70265] dispatch_once:单次执行任务;只会执行一次,重复调用方法也不会重复执行(可用于应用程序中初始化全局数据的情况,例如:单例模式) 3 2015-08-30 17:19:44.229 GCDDemo[4776:70265] Current thread:
{number = 4, name = (null)}, imageIndex:11 4 2015-08-30 17:19:44.230 GCDDemo[4776:70114] 主队列异步(同步也一样),线程:
{number = 1, name = main} 5 2015-08-30 17:19:44.283 GCDDemo[4776:70265] Current thread:
{number = 4, name = (null)}, imageIndex:0 6 2015-08-30 17:19:44.283 GCDDemo[4776:70114] 主队列异步(同步也一样),线程:
{number = 1, name = main} 7 2015-08-30 17:19:44.301 GCDDemo[4776:70248] Current thread:
{number = 2, name = (null)}, imageIndex:1 8 2015-08-30 17:19:44.301 GCDDemo[4776:70114] 主队列异步(同步也一样),线程:
{number = 1, name = main} 9 2015-08-30 17:19:44.516 GCDDemo[4776:70269] Current thread:
{number = 5, name = (null)}, imageIndex:210 2015-08-30 17:19:44.516 GCDDemo[4776:70114] 主队列异步(同步也一样),线程:
{number = 1, name = main}11 2015-08-30 17:19:44.887 GCDDemo[4776:70241] Current thread:
{number = 6, name = (null)}, imageIndex:612 2015-08-30 17:19:44.888 GCDDemo[4776:70114] 主队列异步(同步也一样),线程:
{number = 1, name = main}13 2015-08-30 17:19:44.999 GCDDemo[4776:70299] Current thread:
{number = 7, name = (null)}, imageIndex:314 2015-08-30 17:19:44.999 GCDDemo[4776:70114] 主队列异步(同步也一样),线程:
{number = 1, name = main}15 2015-08-30 17:19:45.152 GCDDemo[4776:70301] Current thread:
{number = 8, name = (null)}, imageIndex:516 2015-08-30 17:19:45.152 GCDDemo[4776:70114] 主队列异步(同步也一样),线程:
{number = 1, name = main}17 2015-08-30 17:19:45.190 GCDDemo[4776:70300] Current thread:
{number = 9, name = (null)}, imageIndex:418 2015-08-30 17:19:45.190 GCDDemo[4776:70114] 主队列异步(同步也一样),线程:
{number = 1, name = main}19 2015-08-30 17:19:45.240 GCDDemo[4776:70304] Current thread:
{number = 10, name = (null)}, imageIndex:820 2015-08-30 17:19:45.240 GCDDemo[4776:70114] 主队列异步(同步也一样),线程:
{number = 1, name = main}21 2015-08-30 17:19:45.314 GCDDemo[4776:70305] Current thread:
{number = 11, name = (null)}, imageIndex:1022 2015-08-30 17:19:45.314 GCDDemo[4776:70114] 主队列异步(同步也一样),线程:
{number = 1, name = main}23 2015-08-30 17:19:45.443 GCDDemo[4776:70302] Current thread:
{number = 12, name = (null)}, imageIndex:724 2015-08-30 17:19:45.443 GCDDemo[4776:70114] 主队列异步(同步也一样),线程:
{number = 1, name = main}25 2015-08-30 17:19:45.615 GCDDemo[4776:70303] Current thread:
{number = 13, name = (null)}, imageIndex:926 2015-08-30 17:19:45.615 GCDDemo[4776:70114] 主队列异步(同步也一样),线程:
{number = 1, name = main}27 2015-08-30 17:19:45.620 GCDDemo[4776:70114] 自定义组通知,线程:
{number = 1, name = main}28 2015-08-30 17:19:45.620 GCDDemo[4776:70114] 全部的 dispatch_group_async 任务执行完毕后,做一些事情,只执行一次29 2015-08-30 17:19:46.360 GCDDemo[4776:70114] dispatch_after:延时执行任务,这里2.0秒后做一些事情 

方法一:dispatch_async

1 2015-08-30 17:15:08.490 GCDDemo[4668:66939] 全局并发队列异步,线程:
{number = 2, name = (null)} 2 2015-08-30 17:15:08.490 GCDDemo[4668:66894] dispatch_once:单次执行任务;只会执行一次,重复调用方法也不会重复执行(可用于应用程序中初始化全局数据的情况,例如:单例模式) 3 2015-08-30 17:15:08.862 GCDDemo[4668:66939] Current thread:
{number = 2, name = (null)}, imageIndex:11 4 2015-08-30 17:15:08.862 GCDDemo[4668:66894] 主队列异步(同步也一样),线程:
{number = 1, name = main} 5 2015-08-30 17:15:09.062 GCDDemo[4668:66981] Current thread:
{number = 4, name = (null)}, imageIndex:3 6 2015-08-30 17:15:09.062 GCDDemo[4668:66894] 主队列异步(同步也一样),线程:
{number = 1, name = main} 7 2015-08-30 17:15:09.066 GCDDemo[4668:66939] Current thread:
{number = 2, name = (null)}, imageIndex:0 8 2015-08-30 17:15:09.067 GCDDemo[4668:66894] 主队列异步(同步也一样),线程:
{number = 1, name = main} 9 2015-08-30 17:15:09.323 GCDDemo[4668:66941] Current thread:
{number = 5, name = (null)}, imageIndex:210 2015-08-30 17:15:09.323 GCDDemo[4668:66894] 主队列异步(同步也一样),线程:
{number = 1, name = main}11 2015-08-30 17:15:09.323 GCDDemo[4668:66940] Current thread:
{number = 6, name = (null)}, imageIndex:112 2015-08-30 17:15:09.324 GCDDemo[4668:66942] Current thread:
{number = 7, name = (null)}, imageIndex:413 2015-08-30 17:15:09.327 GCDDemo[4668:66894] 主队列异步(同步也一样),线程:
{number = 1, name = main}14 2015-08-30 17:15:09.330 GCDDemo[4668:66894] 主队列异步(同步也一样),线程:
{number = 1, name = main}15 2015-08-30 17:15:09.486 GCDDemo[4668:66991] Current thread:
{number = 8, name = (null)}, imageIndex:716 2015-08-30 17:15:09.486 GCDDemo[4668:66894] 主队列异步(同步也一样),线程:
{number = 1, name = main}17 2015-08-30 17:15:10.156 GCDDemo[4668:66988] Current thread:
{number = 9, name = (null)}, imageIndex:518 2015-08-30 17:15:10.156 GCDDemo[4668:66894] 主队列异步(同步也一样),线程:
{number = 1, name = main}19 2015-08-30 17:15:10.208 GCDDemo[4668:66990] Current thread:
{number = 10, name = (null)}, imageIndex:620 2015-08-30 17:15:10.209 GCDDemo[4668:66894] 主队列异步(同步也一样),线程:
{number = 1, name = main}21 2015-08-30 17:15:10.239 GCDDemo[4668:66992] Current thread:
{number = 11, name = (null)}, imageIndex:822 2015-08-30 17:15:10.239 GCDDemo[4668:66894] 主队列异步(同步也一样),线程:
{number = 1, name = main}23 2015-08-30 17:15:10.491 GCDDemo[4668:66894] dispatch_after:延时执行任务,这里2.0秒后做一些事情24 2015-08-30 17:15:10.838 GCDDemo[4668:66993] Current thread:
{number = 12, name = (null)}, imageIndex:925 2015-08-30 17:15:10.838 GCDDemo[4668:66894] 主队列异步(同步也一样),线程:
{number = 1, name = main}26 2015-08-30 17:15:11.489 GCDDemo[4668:66989] Current thread:
{number = 13, name = (null)}, imageIndex:1027 2015-08-30 17:15:11.490 GCDDemo[4668:66894] 主队列异步(同步也一样),线程:
{number = 1, name = main} 

方法二:dispatch_apply

1 2015-08-30 17:15:50.873 GCDDemo[4694:67547] 全局并发队列异步,线程:
{number = 2, name = (null)} 2 2015-08-30 17:15:50.873 GCDDemo[4694:67503] dispatch_once:单次执行任务;只会执行一次,重复调用方法也不会重复执行(可用于应用程序中初始化全局数据的情况,例如:单例模式) 3 2015-08-30 17:15:50.973 GCDDemo[4694:67547] Current thread:
{number = 2, name = (null)}, imageIndex:11 4 2015-08-30 17:15:50.974 GCDDemo[4694:67503] 主队列异步(同步也一样),线程:
{number = 1, name = main} 5 2015-08-30 17:15:51.018 GCDDemo[4694:67546] Current thread:
{number = 4, name = (null)}, imageIndex:1 6 2015-08-30 17:15:51.018 GCDDemo[4694:67503] 主队列异步(同步也一样),线程:
{number = 1, name = main} 7 2015-08-30 17:15:51.078 GCDDemo[4694:67546] Current thread:
{number = 4, name = (null)}, imageIndex:4 8 2015-08-30 17:15:51.078 GCDDemo[4694:67503] 主队列异步(同步也一样),线程:
{number = 1, name = main} 9 2015-08-30 17:15:51.087 GCDDemo[4694:67562] Current thread:
{number = 5, name = (null)}, imageIndex:210 2015-08-30 17:15:51.087 GCDDemo[4694:67503] 主队列异步(同步也一样),线程:
{number = 1, name = main}11 2015-08-30 17:15:51.200 GCDDemo[4694:67547] Current thread:
{number = 2, name = (null)}, imageIndex:012 2015-08-30 17:15:51.200 GCDDemo[4694:67503] 主队列异步(同步也一样),线程:
{number = 1, name = main}13 2015-08-30 17:15:51.271 GCDDemo[4694:67562] Current thread:
{number = 5, name = (null)}, imageIndex:614 2015-08-30 17:15:51.271 GCDDemo[4694:67503] 主队列异步(同步也一样),线程:
{number = 1, name = main}15 2015-08-30 17:15:51.628 GCDDemo[4694:67549] Current thread:
{number = 6, name = (null)}, imageIndex:316 2015-08-30 17:15:51.628 GCDDemo[4694:67503] 主队列异步(同步也一样),线程:
{number = 1, name = main}17 2015-08-30 17:15:51.701 GCDDemo[4694:67546] Current thread:
{number = 4, name = (null)}, imageIndex:518 2015-08-30 17:15:51.701 GCDDemo[4694:67503] 主队列异步(同步也一样),线程:
{number = 1, name = main}19 2015-08-30 17:15:51.800 GCDDemo[4694:67547] Current thread:
{number = 2, name = (null)}, imageIndex:720 2015-08-30 17:15:51.800 GCDDemo[4694:67503] 主队列异步(同步也一样),线程:
{number = 1, name = main}21 2015-08-30 17:15:52.063 GCDDemo[4694:67549] Current thread:
{number = 6, name = (null)}, imageIndex:922 2015-08-30 17:15:52.064 GCDDemo[4694:67503] 主队列异步(同步也一样),线程:
{number = 1, name = main}23 2015-08-30 17:15:52.109 GCDDemo[4694:67562] Current thread:
{number = 5, name = (null)}, imageIndex:824 2015-08-30 17:15:52.110 GCDDemo[4694:67503] 主队列异步(同步也一样),线程:
{number = 1, name = main}25 2015-08-30 17:15:52.295 GCDDemo[4694:67546] Current thread:
{number = 4, name = (null)}, imageIndex:1026 2015-08-30 17:15:52.295 GCDDemo[4694:67503] 主队列异步(同步也一样),线程:
{number = 1, name = main}27 2015-08-30 17:15:52.874 GCDDemo[4694:67503] dispatch_after:延时执行任务,这里2.0秒后做一些事情

 

转载地址:http://twpol.baihongyu.com/

你可能感兴趣的文章
Hack 苹果系统 Api 实现 iOS TableViewCell 侧滑方案
查看>>
用 Python 做一个 H5 游戏机器人
查看>>
Kali Linux渗透测试实战 第一章
查看>>
倒计时获取验证码
查看>>
我眼中的Android Framework
查看>>
网易云信融合CDN方案及实践
查看>>
Flutter初探 上下拉分页请求+计算器实现
查看>>
TensorFlow入门教程
查看>>
HTML5 新特性
查看>>
你知道JavaScript中的结果值是什么吗?
查看>>
python将指定点云文件(asc)转换为PCD格式
查看>>
切图崽的自我修养-[ES6] 异步函数管理方案浅析
查看>>
关于性能优化的那点事——函数节流
查看>>
NPM简单入门
查看>>
Linux Namespace系列(05):pid namespace (CLONE_NEWPID)
查看>>
爬虫学习之基于Scrapy的网络爬虫
查看>>
基于 WebSocket 实现 WebGL 3D 拓扑图实时数据通讯同步(一)
查看>>
Docker利用Jexus独立版部署MVC Demo
查看>>
199. Binary Tree Right Side View
查看>>
ERR_INCOMPLETE_CHUNKED_ENCODING
查看>>