Thread Queue
线程最多同时10 并行线程 (DISPATCH_QUEUE_CONCURRENT)
当你每个线程都开一个 while(true) {} 循环 你再开并行线程时就不能被分配了。这个时候CPU应该是在 500% 以上
//
// ViewController.m
// MultiThread
//
// Created by apple on 14-6-12.
// Copyright (c) 2014年 square. All rights reserved.
//
#import "ViewController.h"
@implementation NSThread (ThreadGetIndex)
-(NSString*)getThreadNum
{
NSString * description = [ self description ] ;
NSRange range;
range.location = [description length] - 5;
range.length = 4;
return [description substringWithRange:range];
}
@end
@implementation ViewController
{
UILabel *labelA;
UILabel *labelB;
UILabel *labelC;
UILabel *heapLabel;
int heapData;
BOOL startD;
BOOL pageStillLoading;
UIProgressView *progress;
}
- (void)viewDidAppear:(BOOL)animated
{
[self exampleWithBlock];
}
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(100, 50, 150, 30)];
[button setTitle:@"开启RunLoop下载" forState:UIControlStateNormal];
[button setBackgroundColor:[UIColor blueColor]];
[button addTarget:self action:@selector(start:) forControlEvents:UIControlEventTouchUpInside];
progress = [[UIProgressView alloc] initWithFrame:CGRectMake(0, 0, 320, 20)];
[progress setTrackTintColor:[UIColor redColor]];
[progress setHidden:YES];
heapLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 80, 150, 50)];
heapLabel.text = [NSString stringWithFormat:@"heap data: %d", heapData];
labelA = [[UILabel alloc] initWithFrame:CGRectMake(0, 150, 300, 50)];
labelB = [[UILabel alloc] initWithFrame:CGRectMake(0, 250, 300, 50)];
labelC = [[UILabel alloc] initWithFrame:CGRectMake(0, 350, 300, 50)];
labelA.font = [UIFont systemFontOfSize:12];
[self.view addSubview:heapLabel];
[self.view addSubview:labelA];
[self.view addSubview:labelB];
[self.view addSubview:labelC];
[self.view addSubview:button];
[self.view addSubview:progress];
// [self multiWithThread];
// [self multiWithDispatch];
[self multiWithOperation];
}
/**
* Thread
*/
- (void)multiWithThread
{
[NSThread detachNewThreadSelector:@selector(threadA) toTarget:self withObject:nil];
[NSThread detachNewThreadSelector:@selector(threadB) toTarget:self withObject:nil];
[NSThread detachNewThreadSelector:@selector(threadC) toTarget:self withObject:nil];
}
/**
* Operation
*
* Task:
* A -> B
* -> D
* C
*
*/
- (void)multiWithOperation
{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSInvocationOperation *opA = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadA) object:nil];
NSInvocationOperation *opB = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadB) object:nil];
NSBlockOperation *opC = [NSBlockOperation blockOperationWithBlock:^{
sleep(2);
[self performSelectorOnMainThread:@selector(showContentWithLabelC:) withObject:[NSString stringWithFormat:@"执行第1次操作,线程:%@",[self threadName]] waitUntilDone:NO];
}];
[opC addExecutionBlock:^{
sleep(3);
[self performSelectorOnMainThread:@selector(showContentWithLabelC:) withObject:[NSString stringWithFormat:@"又执行了一次操作,线程:%@",[self threadName]] waitUntilDone:NO];
}];
NSBlockOperation *opD = [NSBlockOperation blockOperationWithBlock:^{
startD = YES;
// while (startD) {
// [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
// if ([opA isFinished] && [opB isFinished]) {
NSLog(@"终于到我了...");
// startD = NO;
// }
// }
}];
[opB addDependency:opA];
// [opB setCompletionBlock:^{
// [queue addOperation:opD];
// }];
[opD addDependency:opB];
[opD addDependency:opC];
[queue addOperation:opA];
[queue addOperation:opB];
[queue addOperation:opC];
[queue addOperation:opD];
}
/**
* Dispatch
*/
- (void)multiWithDispatch
{
// dispatch_queue_create
// ----
// this is serial, run task by order
//
dispatch_queue_t dis_queue = dispatch_queue_create("com.multiThread.taskA", DISPATCH_QUEUE_SERIAL);
dispatch_async(dis_queue, ^{
[self threadA];
});
dispatch_async(dis_queue, ^{
[self threadB];
});
dispatch_after(DISPATCH_TIME_NOW, dis_queue, ^{
NSLog(@"终于到我了......");
});
//
// dispatch group
//
// dispatch_queue_t queue1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// dispatch_queue_t queue2 = dispatch_queue_create("com.multiThread.taskB", DISPATCH_QUEUE_SERIAL);
// dispatch_group_t group = dispatch_group_create();
// // Add a task to the group
// dispatch_group_async(group, queue1, ^{
// [self threadA];
// });
//
// dispatch_group_async(group, queue2, ^{
// [self threadB];
// });
//
// dispatch_group_wait(group, DISPATCH_TIME_NOW);
// dispatch_get_global_queue
// --
// this is concurrent, run task by async
//
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self threadC];
});
// ------
// go to work after delay 5 sec
// will stuck main thread
//
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// [self threadC];
// });
}
#pragma mark - threads
- (NSString*)threadName
{
return [NSString stringWithFormat:@"%@", [[NSThread currentThread] getThreadNum]];
}
- (void)threadA
{
@autoreleasepool {
[NSThread sleepForTimeInterval:1.0f];
for (int i = 0; i < 10000; i++) {
@autoreleasepool {
[self performSelectorOnMainThread:@selector(showContentWithLabelA:) withObject:[NSString stringWithFormat:@"Thread A: %@, %d", [self threadName], i] waitUntilDone:YES];
heapData = i;
}
}
}
}
- (void)threadB
{
for (int i = 0; i < 10000; i++) {
@autoreleasepool {
[self performSelectorOnMainThread:@selector(showContentWithLabelB:) withObject:[NSString stringWithFormat:@"Thread B: %@, %d", [self threadName], i] waitUntilDone:YES];
}
}
}
- (void)threadC
{
for (int i = 0; i < 100000; i++) {
@autoreleasepool {
[self performSelectorOnMainThread:@selector(showContentWithLabelC:) withObject:[NSString stringWithFormat:@"Thread C: %@, %d", [self threadName], i] waitUntilDone:YES];
}
}
}
- (IBAction)start:(id)sender
{
pageStillLoading = YES;
[NSThread detachNewThreadSelector:@selector(runInBackground:) toTarget:self withObject:nil];
[progress setHidden:NO];
while (pageStillLoading) {
NSLog(@"runloop…");
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
NSLog(@"runloop end.");
}
[progress setHidden:YES];
}
- (void) runInBackground:(id)arg
{
@autoreleasepool {
// Simmulate web page loading
sleep(5);
// This will not wake up the runloop on main thread!
pageStillLoading = NO;
// Wake up the main thread from the runloop
// [self performSelectorOnMainThread:@selector(wakeUpMainThreadRunloop:) withObject:nil waitUntilDone:NO];
}
}
- (void)wakeUpMainThreadRunloop:(id)arg
{
NSLog(@"wake up main thread run loop.");
}
#pragma mark - UI
- (void)showContentWithLabelA:(NSString*)text
{
labelA.text = text;
heapLabel.text = [NSString stringWithFormat:@"heap data: %d", heapData];
}
- (void)showContentWithLabelB:(NSString*)text
{
labelB.text = text;
heapLabel.text = [NSString stringWithFormat:@"heap data:%d", heapData];
}
- (void)showContentWithLabelC:(NSString*)text
{
labelC.text = text;
heapLabel.text = [NSString stringWithFormat:@"heap data:%d", heapData];
}
#pragma mark - About Block
- (void)exampleWithBlock
{
__block int j = 0;
void (^myBlock)(int) = ^(int c){
j = c;
};
myBlock(3);
NSLog(@"%d", j);
}
@end
/*
* 栅栏
* Barrier
*
* 用来处理并行队列里某些任务必须在稍后执行
*
* dispatch_barrier_async
* dispatch_barrier_async_f
* dispatch_barrier_sync
* dispatch_barrier_sync_f
*
* dispatch_barrier_async是异步的,调用后立刻返回,即使block3到了队列首部,也不
* 会立刻执行,而是等到block1和block2的并行执行完成后才会执行block3,完成后再会
* 并行运行block4。
*
* !!!: 注意这里的queue应该是一个并行队列,而且必须是dispatch_queue_create(label, attr)
* 创建的自定义并行队列,dispatch_get_global_queue 或主队列都不行,因为主队列也
* 是串行的,全局队列是不受你控制的。
*
*/
dispatch_queue_t queue = dispatch_queue_create("task", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"1");
});
dispatch_async(queue, ^{
NSLog(@"2");
});
dispatch_barrier_async(queue, ^{
NSLog(@"我一定第3执行");
});
dispatch_async(queue, ^{
NSLog(@"4");
});
/*
* Thread
* dispatch_async(...) 分配一个线程调度
* dispatch_sync(...) 在当前线程调度,如果当前线程是主线程,那么分配的任务也是在主线程
*
* 简化了 NSOperationQueue 的创建与分配,最终目的同样也是创建 Queue 在不同的线程执行
*
* Queue
* DISPATCH_QUEUE_SERIAL 串行
* DISPATCH_QUEUE_CONCURRENT 并行
*
* 串行队列所有的Block都由一个线程来执行(同应用主线程一样),而并发队列会把队列
* 里的Block分发到不同的线程来执行。
*
*/
// 当前线程,队列信息, 推荐只在 Debug 环境下使用
dispatch_get_current_queue()
// get queue label
dispatch_queue_get_label(queue)
// 串行队列,顺序执行各自任务
dispatch_queue_create("com.multiThread.taskA", DISPATCH_QUEUE_SERIAL)
// 并行队列,同时执行队列中的任务,推荐!!!
dispatch_queue_create("com.multiThread.taskA", DISPATCH_QUEUE_CONCURRENT)