Fork me on GitHub

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);

 

posted on 2012-02-19 02:51  pengyingh  阅读(525)  评论(0编辑  收藏  举报

导航