Review and learn about GCD and Block. I will post a good article on the basic usage of GCD.
Address: http://blog.csdn.net/aolan1108/article/details/17283415
After two years of ios development, I would like to calm down and think about it and make some conclusions. However, I have never been able to do so because of various causes of my life and work. Today, I have made up my mind to record what I have learned so that I can view it later and share it with you.
As I said before, after two years of ios development, I only know the continuous copy code. If you want to really ask me that GCD is a great thing, I will not be clear at half past one. Here I want to feel lucky for myself to survive in the Internet age. I have read a lot of information on the Internet, most of which are incomplete. In these materials, I continue to screen, finally, I understood GCD. I don't like to talk about anything officially. From the perspective of his definition, this is a conventional one. If you really don't understand what GCD means, you can find it on your own. Queue type: 1. Main queue of the Main thread, which is obtained through dispatch_get_main_queue. 2. Parallel queue global dispatch queue, which is obtained through dispatch_get_global_queue and created by the system (which does not need to be created by developers. The execution sequence of the parallel queue is the same as that of the queue. Iii. serial queue serial queues is generally used for sequential synchronous access. You can create any number of serial queues, and each serial queue is concurrent. Generally, dispatch_queue_create is used to create a queue. In non-arc scenarios, You need to manually release the queue. Some people may say that since the queue is also an object, you can create and release it, there must be a reference counter. Yes, you can use the dispatch_retain and dispatch_release functions to increase or decrease the reference counter. Submit a job: Before giving you an example, I want to talk about two job submission methods: dispatch_async and dispatch_sync, which are asynchronous and synchronous. The difference between the two is that, the former does not cause blocking when submitting a task to the queue for execution, while the code block after the latter can be executed only after the tasks in the queue are completed. The following is an example 1. We can see that the second print statement is executed first, which indicates that this statement is not blocked.
[Objc]View plaincopy
// Asynchronous execution of the main thread-(void) action1 {dispatch_async (dispatch_get_main_queue (), ^ {for (int I = 0; I <5; I ++) NSLog (@ "Asynchronous execution of the main thread =============% d", I );}); NSLog (@ "====================== asynchronous execution of the main thread ");}
Print result:
14:36:20. 863 TestGCD [872: a0b] ======================= asynchronous execution of the main thread
14:36:20. 864 TestGCD [872: a0b] asynchronous execution of the main thread ============= 0
14:36:20. 865 TestGCD [872: a0b] asynchronous execution of the main thread ============ 1
14:36:20. 865 TestGCD [872: a0b] asynchronous execution of the main thread ============= 2
14:36:20. 865 TestGCD [872: a0b] asynchronous execution of the main thread ============= 3
14:36:20. 866 TestGCD [872: a0b] asynchronous execution of the main thread ============= 4
Example 2: Someone may ask, since the main thread can be executed asynchronously, the main thread can also be executed synchronously. Yes, but you cannot change dispatch_async to dispatch_sync directly in action1. This modification is meaningless. You can try it and the tasks in it will not be executed at all.
[Objc]View plaincopy
// Synchronous execution of the main thread-(void) action2 {dispatch_async (dispatch_get_global_queue (0, 0), ^ {for (int I = 0; I <3; I ++) NSLog (@ "concurrent thread asynchronous execution =============% d", I); dispatch_sync (dispatch_get_main_queue (), ^ {for (int I = 0; I <3; I ++) NSLog (@ "Master thread synchronous execution ===============% d ", i) ;}); NSLog (@ "============= the execution of the main thread is completed ");}); NSLog (@ "=========== concurrent threads may be executing ");}
Print result:
15:22:22. 352 TestGCD [1269: a0b] =========== the concurrent thread may be executing
15:22:22. 352 TestGCD [1269: 1403] concurrent thread asynchronous execution ============= 0
15:22:22. 355 TestGCD [1269: 1403] concurrent thread asynchronous execution ============ 1
15:22:22. 356 TestGCD [1269: 1403] concurrent thread asynchronous execution ============= 2
15:22:22. 357 TestGCD [1269: a0b] synchronous execution of the master thread ============= 0
15:22:22. 358 TestGCD [1269: a0b] synchronous execution of the master thread ============ 1
15:22:22. 358 TestGCD [1269: a0b] Master thread synchronous execution =============== 2
15:22:22. 359 TestGCD [1269: 1403] =========== the execution of the main thread is complete
From the results, we will have a deep understanding. First, we can see that print Statement 4 is executed first (it may not be the first execution, which is determined by the system ), it indicates that the execution method submitted to the concurrent queue dispatch_get_global_queue is asynchronous, and the execution of print Statement 2 starts after print Statement 1 is executed. This indicates that dispatch_get_global_queue is a concurrent queue, however, the execution sequence of the internal tasks is serial. Finally, we can see that print Statement 3 is executed after print Statement 2 is executed. This indicates that the synchronous execution of the main thread is blocked, we usually put the UI refresh in synchronous mode into the main thread for operations. Of course, this operation usually takes a short time, so that users can hardly notice it.
Example 3: in fact, the true significance of GCD operations is not to perform some operations in the main thread. In many cases, we will use background threads. If your iphone is a multi-core cpu, congratulations, you can have a smooth operation experience, even if it is not a multi-core, your operation experience is relatively smooth, because you can put a task that takes a lot of time to complete in the background thread for execution, the user will not feel dead, such as image loading, network requests, complex logic data parsing, and so on.
// Asynchronous execution in the background
-(Void) action3 {dispatch_async (dispatch_get_global_queue (0, 0), ^ {for (int I = 0; I <10000; I ++) NSLog (@ "===========================% d", I );}); NSLog (@ "========================= background asynchronous execution ");}
You can click the button twice quickly to execute the action3 method twice in a row. Here, we take part of the print result:
15:51:30. 864 TestGCD [1350: 3007] ==================== 0
15:51:30. 864 TestGCD [1350: a0b] ======================= background asynchronous execution
15:51:30. 864 TestGCD [1350: 3007] ==================== 1
15:51:30. 865 TestGCD [1350: 3007] ======================= 2
15:51:30. 865 TestGCD [1350: 3007] ======================= 3
......
15:51:31. 007 TestGCD [1350: 3007] ====================== 600
15:51:31. 007 TestGCD [1350: 3007] ====================== 601
15:51:31. 007 TestGCD [1350: a0b] ========================= background asynchronous execution
15:51:31. 007 TestGCD [1350: 3007] ====================== 602
15:51:31. 008 TestGCD [1350: 3007] ====================== 603
15:51:31. 007 TestGCD [1350: 473] ====================== 0
15:51:31. 008 TestGCD [1350: 473] ==================== 1
15:51:31. 008 TestGCD [1350: 473] ========================= 2
15:51:31. 008 TestGCD [1350: 3007] ====================== 604
15:51:31. 008 TestGCD [1350: 473] =====================3
15:51:31. 008 TestGCD [1350: 3007] ====================== 605
......
We can see that because action3 is executed twice, after the first click, the screen still accepts the click Time, indicating that the main thread is not blocked and the user experience is still smooth. Two clicks actually submit two tasks to the dispatch_get_global_queue queue. The first task is not completed and the second task starts to be executed. This indicates that dispatch_get_global_queue is a parallel queue, that is, the task block and the task block are executed concurrently.
In Example 4, some friends say that the background can be asynchronously executed, so it should also be able to be executed synchronously. Yes, you are right, but there is no significance in the actual development process, we will find that the modification method will cause blocking, but it cannot be used to refresh the UI, nor reflect the advantages of multi-core processors.
// Synchronous execution in the backend-(void) action4 {dispatch_sync (dispatch_get_global_queue (0, 0), ^ {for (int I = 0; I <10000; I ++) NSLog (@ "===========================% d", I );}); NSLog (@ "========================= background synchronous execution ");}
We also click the button twice in a row to execute the action4 method twice. We are surprised to see the print result. Some people may say that the dispatch_get_global_queue queue is not a concurrent queue, the execution result is as follows. Here I need to explain that because the execution method submitted to the Global queue is synchronous, blocking occurs, that is, the following task can be executed only after the task is completed, we can see the position where print Statement 2 is executed. Therefore, synchronization is generally used to refresh the UI or process shared data, and the processing time of the task cannot be too long, which will affect the user experience.
16:04:35. 967 TestGCD [1385: a0b] ====================== 0
16:04:35. 969 TestGCD [1385: a0b] ==================== 1
16:04:35. 969 TestGCD [1385: a0b] ========================= 2
......
16:04:40. 645 TestGCD [1385: a0b] ====================== 9997
16:04:40. 645 TestGCD [1385: a0b] ====================== 9998
16:04:40. 646 TestGCD [1385: a0b] ====================== 9999
16:04:40. 646 TestGCD [1385: a0b] ======================= background synchronous execution
16:04:40. 647 TestGCD [1385: a0b] ====================== 0
16:04:40. 647 TestGCD [1385: a0b] ==================== 1
16:04:40. 648 TestGCD [1385: a0b] ========================= 2
16:04:40. 648 TestGCD [1385: a0b] =======================3
......
16:04:45. 218 TestGCD [1385: a0b] ====================== 9998
16:04:45. 218 TestGCD [1385: a0b] ====================== 9999
16:04:45. 218 TestGCD [1385: a0b] ======================= background synchronous execution
Example 5: A developer can define a queue to execute background threads. Similar to the global queue, a developer needs to manually release a queue without arc.
// Custom queue-(void) action5 {queue urls_queue = dispatch_queue_create ("myQueue", NULL); dispatch_async (urls_queue, ^ {for (int I = 0; I <5; I ++) NSLog (@ "Custom dispatch_queue_t ========== % d", I); dispatch_sync (dispatch_get_main_queue (), ^ {NSLog (@ "interaction with the main thread ============") ;}); dispatch_release (urls_queue); // arc do not}
Print result:
16:43:52. 416 TestGCD [1464: 1417] custom dispatch_queue_t =========== 0
16:43:52. 417 TestGCD [1464: 1417] custom dispatch_queue_t ========== 1
16:43:52. 418 TestGCD [1464: 1417] custom dispatch_queue_t =========== 2
16:43:52. 419 TestGCD [1464: 1417] custom dispatch_queue_t =========== 3
16:43:52. 420 TestGCD [1464: 1417] custom dispatch_queue_t =========== 4
16:43:52. 420 TestGCD [1464: a0b] interacts with the main thread ============
Example 6: The scheduling method is also delayed.
// Execution is delayed for 3 seconds-(void) action6 {double delayInSeconds = 3.0; interval popTime = dispatch_time (interval, (int64_t) (delayInSeconds * NSEC_PER_SEC); dispatch_after (popTime, dispatch_get_main_queue (), ^ (void) {NSLog (@ "3 seconds delayed execution ============== ");});}
Print result:
16:48:58. 473 TestGCD [1484: a0b] execution delayed for 3 seconds ==============
Example 7: one-time execution, mainly used to create a singleton object. Before ios4.0, we used mutex lock @ synchronized to create a single meeting to ensure that other threads did not modify the self object, which is generally used when sharing variables.
+ (NetworkManager *)getNetworkInstance{ @synchronized(self){ if (nil == network) network = [[NetworkManager alloc] init]; } return network; }
After ios4.0, we can use GCD to create a singleton. The following GCD syntax is executed only once. The Code is as follows:
+(UserManager *)sharedManager{ static UserManager *_manager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _manager = [[UserManager alloc]init]; }); return _manager; }
The advantages of this method include: 1. thread security; 2. satisfying the requirements of static analyzer; 3. compatible with ARC; 4. requiring only a small amount of code.
Example 8: Merge the summary results. The dispatch_group_t queue is very useful. When we have multiple asynchronous execution queues, we also use dispatch_group_t when we need to use the results of multiple asynchronous execution queues for a task. If you don't need to talk about it, go directly to the Code:
// Merge the summary result-(void) action8 {dispatch_group_t group = dispatch_group_create (); dispatch_group_async (group, dispatch_get_global_queue (0, 0), ^ {for (int I = 0; I <5; I ++) NSLog (@ "Parallel Execution thread 1 =================% d", I );}); dispatch_group_async (group, dispatch_get_global_queue (0, 0), ^ {for (int I = 0; I <5; I ++) NSLog (@ "Parallel Execution thread 2 =================% d", I) ;}); dispatch_group_notify (group, dispatch_get_global_queue (0, 0), ^ {NSLog (@ "Summary Result =");}); dispatch_release (group );}
Print result:
11:48:39. 139 TestGCD [699: 1403] parallel execution thread 1 ================= 0
11:48:39. 139 TestGCD [699: 3807] parallel execution thread 2 ================= 0
11:48:39. 143 TestGCD [699: 1403] parallel execution thread 1 ================ 1
11:48:39. 143 TestGCD [699: 3807] parallel execution thread 2 ================ 1
11:48:39. 144 TestGCD [699: 1403] parallel execution thread 1 ================= 2
11:48:39. 144 TestGCD [699: 3807] parallel execution thread 2 ================= 2
11:48:39. 145 TestGCD [699: 1403] parallel execution thread 1 ================= 3
11:48:39. 145 TestGCD [699: 3807] parallel execution thread 2 ================= 3
11:48:39. 146 TestGCD [699: 3807] parallel execution thread 2 ================= 4
11:48:39. 146 TestGCD [699: 1403] parallel execution thread 1 ================= 4
11:48:39. 147 TestGCD [699: 3807] Summary Result ============
We can see that the third print statement is executed only after the first two print statements are executed.
This is what I have summarized from the official documents and a lot of online materials, and I want to help you with the actual code debugging results, you are welcome to give different comments.
Reference: http://www.cnblogs.com/pure/archive/2013/03/31/2977420.html