Original blog, reproduced please indicate the source
Blog.csdn.net/hello_hwc
Welcome to my iOS SDK detailed column
Http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html
Foreword: A bit busy recently, so the number of blogs updated this month has dropped somewhat, estimated that this month and next month the number of blog update is about 10 articles. Back to the point, this article will compare the GCD and nsoperation two kinds of multi-threaded implementation methods. Then explain how to choose, as well as a simple example.
Choose GCD or Nsoperationqueue?
In fact, there is no standard answer, Nsoperationqueue is the upper package of GCD, what is the package? is to pack some functionality together and provide it to the developer. There's a principle in iOS development
The upper-level API is preferred, unless the upper API is not implemented, or if there are performance issues after implementation, the underlying is selected.
In fact, different people have different understandings and habits about this problem. The personal opinion is that the analysis of the nature of their own tasks, in the following cases, priority consideration Nsoperationqueue
- A dependency between tasks
- Limit the maximum number of tasks that can be performed.
- The mission could have been canceled.
GCD is preferred in the following cases:
- Task is a simple block submission
- Complex block nesting is required between tasks
- Tasks require very frequent submissions. (Simply mention this, because Nsoperation is an object that allocates extra memory and frees up memory if the process is very frequent and CPU loss is huge)
About the simple block
GCD can be conveniently used block, for example
dispatch_async0), ^(void) { //后台操作 dispatch_async(dispatch_get_main_queue(), ^(void) { //主线程更新UI }); });
Here, you can copy this code for Sanipet, which makes it easy to use.
dispatch_async(dispatch_get_global_queue(<#dispatch_queue_priority_t priority#>, <#unsigned long flags#>), ^(void) { <#code#> dispatch_async(dispatch_get_main_queue(), ^(void) { <#code#> });})
Then set the parameters
The personal habit here is that snipet use the name prefix _quick, which can be done according to personal habits.
Of course, Nsoperation also support the submission of block, but it is not gcd convenient to use
queue = [[NSOperationQueue alloc] init]; [queue addOperationWithBlock:^{ //后台操作 [[NSOperationQueue mainQueue] addOperationWithBlock:^{ //主线程更新UI }]; }];
Here, why is inconvenient, because Nsoperationqueue is an object, the object you have to consider its life cycle (when created, when released), it is obviously not gcd handy more.
There is a dependency between tasks
This is one of the most frequently used topics I've been recruiting recently:
There are three tasks, task one and task two can be carried out at the same time, task three must be done after task one and task two are completed before it can be executed. Finally, all three tasks are completed to inform the user.
See how it's achieved with Nsoperationqueue
Nsoperationqueue * queue = [[Nsoperationqueue alloc] init]; Nsblockoperation * Task1 = [nsblockoperation blockoperationwithblock:^{sleep (1); NSLog (@"Task1 is done"); }]; Nsblockoperation * Task2 = [nsblockoperation blockoperationwithblock:^{sleep (2); NSLog (@"Task2 is done"); }]; Nsblockoperation * Task3 = [nsblockoperation blockoperationwithblock:^{sleep (1); NSLog (@"Task3 is done"); }]; [Task3 Adddependency:task1]; [Task3 Adddependency:task2]; Nsblockoperation * DoneOperation = [Nsblockoperation blockoperationwithblock:^{NSLog (@"All Tasks are done"); }]; [ DoneOperation Adddependency:task1]; [ DoneOperation Adddependency:task2]; [ DoneOperation Adddependency:task3]; [Queue Addoperations:@[task1,task2,task3, DoneOperation] Waituntilfinished:no];
Output
2015-06-2711::. 936 OCTest[1189:72220] Task1 is Done2015-06-2711::. 938 OCTest[1189:72219] Task2 is Done2015-06-2711::. 940 OCTest[1189:72219] Task3 is Done2015-06-2711::. 940 OCTest[1189:72219] All Task is Done
and see how it's implemented with GCD.
Analysis of how to achieve, in fact, and a variety of implementation methods, such as the number of signal control tasks, such as with Dispatchgroup. Here, I choose to use Dispatch_group to achieve
dispatch_group_t group = Dispatch_group_create ();dispatch_queue_tGlobalqueue = Dispatch_get_global_queue (Dispatch_queue_priority_default,0); Dispatch_group_async (Group, Globalqueue, ^{sleep (1);NSLog(@"Task1 is done"); }); Dispatch_group_async (Group, Globalqueue, ^{sleep (2);NSLog(@"Task2 is done"); }); Dispatch_group_notify (Group, Globalqueue, ^{Dispatch_async(Globalqueue, ^{sleep (1);NSLog(@"Task3 is done");Dispatch_async(Dispatch_get_main_queue (), ^{NSLog(@"All Tasks are done"); }); }); });
Output
2015-06-2711:: Approx .. 306 OCTest[1245:76887] Task1 is Done2015-06-2711:: Panax Notoginseng. 306 OCTest[1245:76886] Task2 is Done2015-06-2711::. 311 OCTest[1245:76886] Task3 is Done2015-06-2711::. 312 OCTest[1245:76856] All Task is Done
At first glance, it's good to have a gcd dependency relationship. However, it is important to be clear that GCD does not have a clear dependency, and that the dependency should be implemented by the developer themselves, and when the dependencies are complex, it is easy to make mistakes.
About Complex block nesting
For example, such nesting, GCD is easy to implement, and nsoperation implementation is more complex.
dispatch_queue_t0); dispatch_async(globalQueue, ^{ //Do something dispatch_async(dispatch_get_main_queue(), ^{ //Do something with UI dispatch_async(globalQueue, ^{ //Do something dispatch_async(dispatch_get_main_queue(), ^{ //Do something with UI }); }); }); });
About task cancellation
GCD there is no obvious task cancellation, you need to implement the task to cancel. For example, keep checking for a bool flag, and if true, return early
Nsoperation can be easily canceled.
Finally, mention the two subcategories of nsoperation
Nsblockoperation
Used to encapsulate a block into a nsoperation.
NSOperation * blockOperation = [NSBlockOperation blockOperationWithBlock:^{ //Block }];
Nsinvocationoperation
Encapsulates a selector into a nsoperation
NSInvocationOperation * operation = [[NSInvocationOperation alloc] initWithTarget:selfselector:@selector(function) object:nil];-(void)function{ NSLog(@"function");}
Copyright NOTICE: This article is for bloggers original article, if you need to reprint please indicate the source
IOS multithreaded Development Operationqueue (ii) nsoperation VS GCD