Concurrency 学习 (Mac & iphone)
Concurrency是ios4.0和macosx10.6引入的一个新的东西
根据我的学习和了解Concurrency就是为了更好的使用多核CPU,在单核下使用thread就可以, 但是在多核下使用thread不能很好的发挥多核的优势,用以更好的实现多任务.
Concurrency 使用技术
异步模式 (asynchronous design approach)
Grand Central Dispatch (需要以后近一步研究,意思就是自动管理线程运行,线程代码可以在更高效的系统层运行)
Operation queues Dispatch Queues Dispatch Sources
1)Operation queues
//声明一个NSOperationQueue 这个就是任务操作的concurrency
aQueue = [[NSOperationQueue alloc] init];
a)NSInvocationOperation
//使用的时候如下
{
NSInvocationOperation * opt = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doInvocation) object:NULL];
//可以加到我们前面声明的队列中
[aQueue addOperation:opt];
//也可以加到默认的当前队列中
// [[NSOperationQueue currentQueue] addOperation:opt];
//也可以加到主队列中 主线程运行这个很有用的
// [[NSOperationQueue mainQueue] addOperation:opt];
[opt release];
return;
}
- (void)doInvocation
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSLog(@"doInvocation from NSInvocationOperationButton");
[pool release];
}
b)NSBlockOperation
{
NSBlockOperation * opt = [[NSBlockOperation alloc] init];
int s = 100;
[opt addExecutionBlock:^{
NSLog(@"Run in block %d",s);
}];
[aQueue addOperation:opt];
//[[NSOperationQueue mainQueue] addOperation:opt];
//[[NSOperationQueue currentQueue] addOperation:opt];
[opt release];
}
//这里用到一个mac和ios一个很有趣的东西block以后会深入研究,block是在系统级运行却能访问类中的数据甚至函数中的数据
3) Custom Operation
定义用户自己的Operation首先要确定是非并发Operation还是并发Operation
定义非并发Operation只需要定义main函数
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
}
return self;
}
- (void)dealloc {
[super dealloc];
}
-(void)main {
@try {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
// Do some work on myData and report the results.
[pool release];
}
@catch(...) {
// Do not rethrow exceptions.
}
}
定义并发Operation除了需要定义main函数 还需要overwrite
start
isExecuting
isFinished
isConcurrent
- (id)init
{
self = [super init];
if (self) {
executing = NO;
finished = NO;
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
//既然使用concurrent 这里一定是YES
- (BOOL)isConcurrent {
return NO;
}
- (BOOL)isExecuting {
return executing;
}
- (BOOL)isFinished {
return finished;
}
-(void)main
{
@try
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Do ConcurrentOperation");
[self completeOperation];
[pool release];
}
@catch(...) {
NSLog(@"Do ConcurrentOperation catch error");
}
}
- (void)start {
NSLog(@"Do ConcurrentOperation start ");
if ([self isCancelled])
{
[self willChangeValueForKey:@"isFinished"];
finished = YES;
[self didChangeValueForKey:@"isFinished"];
return;
}
[self willChangeValueForKey:@"isExecuting"];
[NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil];
executing = YES;
[self didChangeValueForKey:@"isExecuting"];
}
- (void)completeOperation
{
[self willChangeValueForKey:@"isFinished"];
[self willChangeValueForKey:@"isExecuting"];
executing = NO;
finished = YES;
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
}
Dispatch Queues
Dispatch Queues从使用的角度将更象另一种形式的Operation Queues只是 Operation Queuse是用ObjectC的Dispatch Queues是C的
dispatch Queues有serial Queues 也被称为私有dispatch Queues,一个时间只能运行一个task,顺序运行
dispatch_queue_t queue;
queue = dispatch_queue_create("myQueue", NULL);
dispatch_async(queue, ^{
printf("Do some work here.\n");
});
printf("The first block may or may not have run.\n");
dispatch_sync(queue, ^{
printf("Do some more work here.\n");
});
printf("Both blocks have completed.\n");
这里使用了同步dispatch和异步dispatch,推荐使用dispatch_async这样才能真正体现其中的优势同步相当于WaitUntil = YES
还有一种就是Concurrent Queues每个程序系统自动提供了3个Concurrent Queues
dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t aHQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_queue_t aLQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
啥意思一看就明白,3个优先级别的concurrent queues
最后一个特殊的Dispatch Queue就是main dispatch Queue 也是程序启动自动生成
dispatch_queue_t mainQueue = dispatch_get_main_queue();
concurrent queues和main queue 都是由系统生成而且 dispatch_suspend, dispatch_resume, dispatch_set_context,这些函数对他们无效
但是我们的应用不是简单的同步也异步的运行,应用经常是混合的
比如我们要task1 task2 task3 都运行完成后才能异步运行task4 task5 task6我们该怎么做呢?这里我们可以引入group的概念
dispatch_queue_t aDQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
// Add a task to the group
dispatch_group_async(group, aDQueue, ^{
printf("task 1 \n");
});
dispatch_group_async(group, aDQueue, ^{
printf("task 2 \n");
});
dispatch_group_async(group, aDQueue, ^{
printf("task 3 \n");
});
printf("wait 1 2 3 \n");
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
printf("task 1 2 3 finished \n");
dispatch_release(group);
group = dispatch_group_create();
// Add a task to the group
dispatch_group_async(group, aDQueue, ^{
printf("task 4 \n");
});
dispatch_group_async(group, aDQueue, ^{
printf("task 5 \n");
});
dispatch_group_async(group, aDQueue, ^{
printf("task 6 \n");
});
printf("wait 4 5 6 \n");
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
printf("task 4 5 6 finished \n");
dispatch_release(group);
有时候我们也可以将设定一个数据在queue中 也可以定义一个结束函数
dispatch_set_finalizer_f 是在dispatch_release时候被调用
dispatch_queue_t serialQueue = dispatch_queue_create("com.example.CriticalTaskQueue", NULL);
if (serialQueue)
{
dispatch_set_context(serialQueue, self);
dispatch_set_finalizer_f(serialQueue, &myFinalizerFunction);
}
dispatch_group_t group = dispatch_group_create();
// Add a task to the group
dispatch_group_async(group, serialQueue, ^{
printf("task 1 \n");
});
dispatch_group_async(group, serialQueue, ^{
printf("task 2 \n");
});
dispatch_group_async(group, serialQueue, ^{
printf("task 3 \n");
});
printf("wait 1 2 3 \n");
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_release(group);
dispatch_release(serialQueue);