IOS development of multi-threaded

IOS development, multithreading is an important point of knowledge, in the following content, it is necessary to talk about the process and the concept of thread.
process: an application running in the system, each process is independent, each process is running within the exclusive space, and the space is protected, it is a process not to be able to access another process unique space. Processes such as: XCode, Safari, QQ, etc. are running a separate process. Five state model of
process: new, ready, running, blocking, terminating.
thread: thread is the basic unit of execution of the process, all the tasks of the process are executed in the thread, namely a process to implement the tasks must be at least one of the threads, the main thread is what we often say, in the development of iOS also known as the UI thread. A process can open a few threads at the same time, and a thread can only be in a process.
the use of the multi thread scene:


network request file processing, image loading
data storage
, execute
task execution task:
serial: multiple task execution according to certain order.
parallelism: simultaneous execution of multiple tasks.

The advantages and disadvantages of multiple threads:
advantages: 1, simplify the programming model disadvantages: 1, increase programming complexity of
2 and 2, more lightweight memory space and improve the efficiency of the implementation of
3, 3, CPU
4, increase the scheduling overhead and improves the utilization rate of resource

IOS development of multi-threaded implementation program:
pThread, NSThread, GCD, NSOperation

A multi-threaded pThread

PThread is a lot of operating systems are used in multi-threaded API, transplantation is particularly strong in the iOS platform is also possible, but it is based on the C language framework, in the iOS development process with little.

Nonsense on the code:

- (void) viewDidLoad viewDidLoad] UIButton {[super; *btn = [[UIButton alloc] initWithFrame:CGRectMake (100, 100, 100, 50)]; [btn setTitle:@ "pThread" forState:UIControlStateNormal]; [btn setTitleColor:[UIColor redColor] forState: UIControlStateNormal]; [btn addTarget:self action:@selector (clickPthread) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:btn];} - (void) clickPthread{NSLog ("I'm in the thread% @ @ in the implementation of" [NSThread, currentThread]); / * parameters: signifies that the thread object address cannot be empty parameter two: some properties of the thread, which can be empty: three parameter that represents a pointer to a function, this cannot be empty: four parameters need to receive the function parameters, Can be null * / pthread_t pthread; pthread_create (& pthread, NULL, run, NULL);} void *run (void *data) {NSLog (@ "% @ thread in my" [NSThread currentThread] for (int); I = 0; I < I 4; NSLog (+ +) {@ "%d", I); sleep (1) return NULL;}};

Console print results:

2547 / / process only label code, 178761 and 179079 is the only thread marking code 2017-02-23 15:16:55.770 pThreadTest[2547:178761] I < NSThread: 0x600000065a40> in the thread; {number = 1; 2017-02-23 15:16:55.770, executive pThreadTest[2547:179079] I in < name = main}; NSThread: 0x608000068a00> {number = 3, name = (null) 2017-02-23 15:16:55.770 pThreadTest[2547:179079]} thread 0 2017-02-23 15:16:56.771 pThreadTest[2547:179079] 1 2017-02-23 15:16:57.777 pThreadTest[2547:179079] 2 2017-02-23 15:16:58.779 pThreadTest[2547:179079] 3

Two, multi-threaded NSThread

Object oriented, we can directly manipulate thread objects.
nonsense on the code:

- (void) viewDidLoad viewDidLoad] UIButton {[super; *btn = [[UIButton alloc] initWithFrame:CGRectMake (100, 150, 100, 50)]; [btn setTitle:@ "NSThread" forState:UIControlStateNormal]; [btn setTitleColor:[UIColor redColor] forState: UIControlStateNormal]; [btn addTarget:self action:@selector (clickNSThread) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:btn];} - (void) clickNSThread{NSLog (@ "% @ in my thread in the implementation of" [NSThread, currentThread]); / / //1. alloc init by way of creating and executing thread / / NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector object:nil] (runThread1); / / [thread1 / / start]; / / //2. detachNewThreadSelector by the way of creating and executing The thread / / [NSThread detachNewThreadSelector:@selector (runThread1) toTarget:self withObject:nil]; //3. by performSelectorInBackground thread [self (runThread1) performSelectorInBackground:@selector withObject:nil];} - (void) runThread1{NSLog (@ "I% @ thread", [NSThread currentThread] for (int); I = 0; I < I 4; NSLog (+ +) {@ "%d", I); sleep (1); if (I = = 3) {/ / back to the main thread executing [self (runMainThread) performSelectorOnMainThread:@ selector withObject:nil waitUntilDone:YES];}}} - (void) runMainThread{NSLog (@ "I% @ thread, [NSThread currentThread]);}

Console print results:

2017-02-23 15:48:49.561 pThreadTest[2642:199011] I NSThread: 0x60000007f9c0> in < {number = 1; 2017-02-23 15:48:49.562 pThreadTest[2642:199229], executive at < name = main} NSThread: 0x600000270cc0> thread; {number = 3, name = (null) 2017-02-23 15:48:49.562} thread pThreadTest[2642:199229] 0 2017-02-23 15:48:50.628 pThreadTest[2642:199229] 1 2017-02-23 15:48:51.702 pThreadTest[2642:199229] 2 2017-02-23 15:48:52.776 pThreadTest[2642:199229] 3 2017-02-23 15:48:53.852 pThreadTest[2642:199011] I in < NSThread: 0x60000007f9c0> {number = 1, name = main} thread

Set thread properties:

//1. alloc init by way of creating and executing threads (with more, because you can get the thread object, set its attributes) NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector (runThread1) object:nil] thread name [thread1; / / set setName:@ "name_thread1"]; / / set the priority of thread [thread1 setThreadPriority:0.2] [thread1 start]; *thread2 = NSThread; [[NSThread alloc] initWithTarget:self selector:@selector (runThread1) object:nil]; [thread2 setName:@ "name_thread2"]; [thread2 setThreadPriority:0.5]; [thread2 start];

Console print results:

2017-02-23 16:05:12.834 pThreadTest[2722:210010] I NSThread: 0x60000007ee80> {number; < 2017-02-23 = 4, 16:05:12.834 pThreadTest[2722:210010] 0 2017-02-23 16:05:12.834 implementation in < name pThreadTest[2722:210009] I = name_thread2} thread; NSThread: 0x60000007f0c0> {number = 3, name = name_thread1} 2017-02-23 16:05:12.835 thread pThreadTest[2722:210009] 0 2017-02-23 16:05:13.835 pThreadTest[2722:210010] 1 2017-02-23 16:05:13.835 pThreadTest[2722:210009] 1 2017-02-23 16:05: 14.837 pThreadTest[2722:210010] 2 2017-02-23 16:05:14.837 pThreadTest[2722:210009] 2 2017-02-23 16:05:15.837 pThreadTest[2722:210010] 3 2017-02-23 16:05:15.838 pThreadTest[2722:210009] 3

You can see the name of the thread1 and the thread2 of the name from the console’s printing results, and at the same time, it can be found that every step of the thread2 execution should be performed with priority thread1. But this priority is not the same as what we call the serial, not to say that the thread2 is fully executed after the completion of the thread1, but the allocation of resources in the CPU when the priority assigned to the thread2, to give priority to its implementation.

NSThread lock use:
directly on the code:

/ / / / TicketManager.h / / pThreadTest / / Created / / by Dustin on 17/2/23. Copyright Dustin. All rights of 2017 / / reserved. / / #import < Foundation/Foundation.h> @interface; TicketManager: NSObject - startToSale (void); / / @end / / TicketManager.m / / pThreadTest / / Created / / by Dustin on 17/2/23. Copyright Dustin. All rights of 2017 / / reserved. / / #import "TicketManager.h" #define Total 50 @interface (TicketManager) @property (nonatomic, assign) int tickets @property; / / the remaining votes (nonatomic, assign) int saleCount; / / @property (nonatomic, strong to sell votes) NSThread *threadBJ; @property (nonatomic, strong) NSThread *threadSH @property (nonatomic, strong); NSCondition *ticketCondition; end @implementation @ TicketMa Nager - (instancetype) init{if (self = [super init]) {self.ticketCondition [[NSCondition alloc] = init]; self.tickets = Total; self.threadBJ = [[NSThread alloc] initWithTarget:self selector:@selector (sale) object:nil]; [self.threadBJ setName:@ "BJ_thread"]; self.threadSH = [[NSThread alloc] initWithTarget:self selector:@selector (sale) object:nil]; [self.threadSH setName:@ "SH_thread"]}; return self;} - (void) sale{while (true) {/ / need to lock, or there may be resources to seize the [self.ticketCondition lock]; / / the lock can / / @synchronized (self) {//tickets> 0 and if tickets (self.tickets > 0) { [NSThread sleepForTimeInterval:0.5]; self.tickets - self.saleCount = Total; self.tickets; NSLog (@ "% @: current ticket:%d,%d, [NSThread currentThread].name sold", self.tickets, self.saleCount);}} / / [self.ticketCondition unlock];}} - (void) startToSale{[self.threadBJ start]; [self.threadSH start] @end;} / / / / / / call controller ViewController.m / / pThreadTest / / by / / Created Dustin on 17/2/23. Copyright Dustin. All rights of 2017 / / reserved. / / #import ViewController.h #import < pthread.h> #import "TicketManager.h" @interface ViewController (@end @implementation ViewController) - (void) viewDidLoad {viewDidLoad] [super; TicketManager = [[TicketManager alloc] init]; [manager startToSale];}

Three, multi-threaded GCD

GCD is a set of solutions for apple to multi-core parallel computing. He can be more reasonable by using the CPU kernel, and can automatically manage the threads of the life cycle, for example, create a thread, thread and task scheduling, we do not need to manually manage, you only need to tell GCD what to do on the line.
synchronous &amp: asynchronous: the difference will not block the current thread, synchronization will block the current thread, and asynchronous will not.

Basic usage code:

- (void) viewDidLoad *btn2 alloc] initWithFrame:CGRectMake {UIButton = [[UIButton (100, 200, 100, 50)]; [btn2 setTitle:@ "GCD" forState:UIControlStateNormal] [btn2 setTitleColor:[UIColor redColor]; forState:UIControlStateNormal]; addTarget:self [btn2 action:@selector (clickGCD) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:btn2];} - (void) clickGCD{NSLog (@ GCD in execution thread% @ ". [NSThread currentThread]); / * dispatch_get_global_queue total bureau 1: set the priority queue with higher priority, give priority to the implementation of #define DISPATCH_QUEUE_PRIORITY_HIGH 2 #define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 #define DISPATCH_QUEUE_PRIORITY_LOW (-2) #define DISPATCH_QUEUE_PRIORITY_ BACKGROUND INT16_MIN / dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NSLog (^{/ / perform time-consuming operation @ "start Task1 in [NSThread currentThread], thread% @"); (//dispatch_get_main_queue) the main thread queue dispatch_async (dispatch_get_main_queue), (^{/ back to the main thread to refresh the UI NSLog (@ "refresh in the UI thread,% @" [NSThread currentThread]);});}});

Console print results:

2017-02-23 16:55:33.964 pThreadTest[2851:246460] GCD < NSThread: in the execution thread; 0x6000000656c0> {number = 1, name = main} 2017-02-23 16:55:33.965 pThreadTest[2851:246949] start Task1 in < NSThread: 0x60800006c9c0> thread; {number = 3, name = 2017-02-23 16:55:33.965 pThreadTest[2851:246460] (null)} refresh in the UI thread < NSThread: 0x6000000656c0>; {number = 1, name = main}

GCD serial queue:
code:

Create a / * queue parameters: the char parameter type two: select the serial or parallel serial parallel DISPATCH_QUEUE_SERIAL DISPATCH_QUEUE_CONCURRENT / dispatch_queue_t queue = dispatch_queue_create (com.GCD.queue, DISPATCH_QUEUE_SERIAL); dispatch_async (queue, NSLog ^{(@ "start task 1"); [NSThread sleepForTimeInterval:2]; NSLog (@ "End Task 1");}); dispatch_async (queue, NSLog ^{(@ "start task 2"); [NSThread sleepForTimeInterval:2]; NSLog (@ "End Task 2");}); dispatch_async (queue, NSLog ^{(@ "start task 3"); [NSThread sleepForTimeInterval:2]; NSLog (@ "End Task 3");});

Console print results:

2017-02-23 17:17:19.370 pThreadTest[2910:261786] start task 17:17:21.376 pThreadTest[2910:261786] end 1 2017-02-23 task 1 2017-02-23 17:17:21.376 pThreadTest[2910:261786] start task 17:17:23.379 pThreadTest[2910:261786] end 2 2017-02-23 task 2 2017-02-23 17:17:23.379 pThreadTest[2910:261786] start task 2017-02-23 17:17:25.383 pThreadTest[2910:261786] end 3 task 3 / three the task is executed, and the thread identification code 261786 is the same, in order to guarantee the orderly implementation of serial queue is in the same thread task.

GCD parallel queue:
code:

Create a / * queue parameters: the char parameter type two: select the serial or parallel serial parallel DISPATCH_QUEUE_SERIAL DISPATCH_QUEUE_CONCURRENT / dispatch_queue_t queue = dispatch_queue_create (com.GCD.queue, DISPATCH_QUEUE_CONCURRENT); dispatch_async (queue, NSLog ^{(@ "start task 1"); [NSThread sleepForTimeInterval:2]; NSLog (@ "End Task 1");}); dispatch_async (queue, NSLog ^{(@ "start task 2"); [NSThread sleepForTimeInterval:2]; NSLog (@ "End Task 2");}); dispatch_async (queue, NSLog ^{(@ "start task 3"); [NSThread sleepForTimeInterval:2]; NSLog (@ "End Task 3");});

Console print results:

2017-02-23 17:20:19.570 pThreadTest[2925:264132] start task 17:20:19.570 pThreadTest[2925:264134] start 2 2017-02-23 task 1 2017-02-23 17:20:19.570 pThreadTest[2925:264131] start task 17:20:21.573 pThreadTest[2925:264134] end 3 2017-02-23 task 1 2017-02-23 17:20:21.573 pThreadTest[2925:264132] end task 2017-02-23 17:20:21.573 pThreadTest[2925:264131] end 2 task 3 / the three tasks are executed concurrently, and the thread has three different identification codes, in order to guarantee the execution of concurrent, parallel the queue open three different threads.

Dispatch_group_t: in the development we often have such needs, in multiple tasks after the asynchronous processing, we need a unified callback notification, to tell us all the tasks are finished, then we also need not go according to the processing of other business. This time we need to use dispatch_group_t.

Upper code:

NSLog (@ "I is the main thread"); dispatch_queue_t queue = dispatch_queue_create (com.GCD.group, DISPATCH_QUEUE_CONCURRENT); dispatch_group_t (group = dispatch_group_create); dispatch_group_async (group, queue, NSLog ^{(@ "start task 1"); [NSThread sleepForTimeInterval:2]; NSLog (@ "End Task 1");}); dispatch_group_async (group, queue, NSLog ^{(@ "start task 2"); [NSThread sleepForTimeInterval:2]; NSLog (@ "End Task 2");}); dispatch_group_async (group, queue, NSLog ^{(@ "start task 3"); [NSThread sleepForTimeInterval:2]; NSLog (@ "End Task 3");}) after all the tasks completed; / / group (group, queue, dispatch_group_notify callback ^{NSLog (@ All Tasks over "); dispatch_async (dispatch_get_main_queue (NSLog), ^{(@" back to the main thread to refresh the UI ");});});

Console print results:

2017-02-23 17:38:06.462 pThreadTest[2984:277621] I 2017-02-23 17:38:06.462 pThreadTest[2984:278062] start is the main thread of task 1 2017-02-23 17:38:06.462 pThreadTest[2984:278066] start task 17:38:06.462 pThreadTest[2984:278067] start 2 2017-02-23 task 3 2017-02-23 17:38:08.464 pThreadTest[2984:278062] end task 17:38:08.464 pThreadTest[2984:278067] end 1 2017-02-23 task 3 2017-02-23 17:38:08.464 pThreadTest[2984:278066] end task 17:38:08.465 pThreadTest[2984:278066] All tasks 2 2017-02-23 over 2017-02-23 17:38:08.465 pThreadTest[2984:277621] back to the main thread to refresh the UI / / by the print results can be seen, thread identification code notification dispatch_group_t after all the tasks over the callback of the identification code (278066) and the main thread (277621), can be determined through the callback That is in the sub thread, and the system did not open a new sliver thread, but in the original mission Zi Xiancheng chose a, therefore, if you receive a callback notification, need to refresh the UI also need to go back to the main thread operation.

In the actual development of the project, we may have such a demand, there are a number of asynchronous requests to be executed, the completion of a unified tell us and then perform the UI operation, so write the following code:

- (void) clickGCD{NSLog (@ "I is the main thread"); dispatch_queue_t queue = dispatch_queue_create (com.GCD.group, DISPATCH_QUEUE_CONCURRENT); dispatch_group_t (group = dispatch_group_create); dispatch_group_async (group, queue, [self ^{sendRequest1:^{NSLog (@ "request1 done");}];}); (group, queue, dispatch_group_async ^{[self sendRequest2:^{NSLog (@ "request2 done");}); / /}]; after all the tasks completed group (group, queue, dispatch_group_notify callback ^{NSLog (@ "All tasks over"); dispatch_async (dispatch_get_main_queue (NSLog), ^{(@ "back to the main thread to refresh the UI");});}}); / / network request 1 - (void) sendRequest1: (void (^) () Block{dispatch_async (dispatch_get_global_queue) (0, 0), NSLog (^{@ "start task 1"); [NSThread sleepForTimeInterval:2]; NSLog (@ "End Task 1"); dispatch_async (dispatch_get_main_queue), ^{(if (block) (block);} {});});} / / network request - 2 (void) sendRequest2: (void) (^) (block{) dispatch_async (dispatch_get_global_queue (0, 0), NSLog (^{@ "start task 2"); [NSThread sleepForTimeInterval:2]; NSLog (@ "End Task 2"); dispatch_async (dispatch_get_main_queue), ^{(if (block) {block}} (););}});

Console print results:

2017-02-23 18:04:07.967 pThreadTest[3082:293445] I 2017-02-23 18:04:07.967 pThreadTest[3082:293706] start is the main thread of task 1 2017-02-23 18:04:07.967 pThreadTest[3082:293704] start task 18:04:07.967 pThreadTest[3082:293707] All tasks 2 2017-02-23 over 2017-02-23 18:04:07.968 pThreadTest[3082:293445] UI 2017-02-23 18:04:09.972 back to the main thread to refresh the pThreadTest[3082:293706] End Task 1 2017-02-23 18:04:09.972 pThreadTest[3082:293704] end task 18:04:09.972 pThreadTest[3082:293445] request1 done 2 2017-02-23 2017-02-23 18:04:09.972 pThreadTest[3082:293445] request2 done / / strange network requests are not executed after the callback notification group completed has ended, this is because of the addition of group operation is asynchronous request, two tasks the moment passed,. Step request is still executing.

To solve the above problem dispatch_group_t provides us with the following enter and leave methods:
code:

- (void) clickGCD{NSLog (@ "I is the main thread"); dispatch_queue_t queue = dispatch_queue_create (com.GCD.group, DISPATCH_QUEUE_CONCURRENT); dispatch_group_t group = dispatch_group_create (dispatch_group_enter); (Group); sendRequest1:^{NSLog (@ self ["request1 done"); dispatch_group_leave (Group);}]; dispatch_group_enter (Group); [self sendRequest2:^{NSLog (@ "request2 done"); dispatch_group_leave (Group);}]; / / group after all the tasks completed callback dispatch_group_notify (group, queue, NSLog ^{(@ "All tasks over"); dispatch_async (dispatch_get_main_queue (NSLog), ^{(@ "back to the main thread to refresh the UI");});});} / / network request 1 - (void) send Request1: (void) (^) (block{) dispatch_async (dispatch_get_global_queue (0, 0), NSLog (^{@ "start task 1"); [NSThread sleepForTimeInterval:2]; NSLog (@ "End Task 1"); dispatch_async (dispatch_get_main_queue), ^{(if (block));}} ({block}););} / / network request 2 - (void) sendRequest2: (void) (^) (block{) dispatch_async (dispatch_get_global_queue (0, 0), NSLog (^{@ "start task 2"); [NSThread sleepForTimeInterval:2]; NSLog (@ "End Task 2"); dispatch_async (dispatch_get_main_queue (if), ^{(block {(block)});});}});

Console print results:

2017-02-23 18:09:43.277 pThreadTest[3115:297830] I 2017-02-23 18:09:43.277 pThreadTest[3115:298153] start is the main thread of task 1 2017-02-23 18:09:43.277 pThreadTest[3115:298155] start task 18:09:45.283 pThreadTest[3115:298155] end 2 2017-02-23 task 2 2017-02-23 18:09:45.283 pThreadTest[3115:298153] end task 18:09:45.283 pThreadTest[3115:297830] request2 done 1 2017-02-23 2017-02-23 18:09:45.283 pThreadTest[3115:297830] request1 done 2017-02-23 18:09:45.284 pThreadTest[3115:298153] All tasks over 2017-02-23 18:09:45.284 pThreadTest[3115:297830] back to the main thread to refresh UI

GCD model single example:
code:

/ / / / testSingle.h / / pThreadTest / / Created / / by Dustin on 17/2/23. Copyright Dustin. All rights of 2017 / / reserved. / / #import < Foundation/Foundation.h> @interface; testSingle: NSObject + shareInstance (instancetype); / / @end / / testSingle.m / / pThreadTest / / Created / / by Dustin on 17/2/23. Copyright Dustin. All rights of 2017 / / reserved. / / #import "testSingle.h" static ID _instance=nil; @implementation + testSingle (instancetype) shareInstance{static dispatch_once_t onceToken; dispatch_once (& onceToken, _instance = [[testSingle alloc] init] ^{; NSLog (@ "init the testSingle");}); return _instance;} / / call controller @end - (void) viewDidLoad {[super viewDidLoa D]; UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake (100, 250, 100, 50)]; [btn setTitle:@ "single" forState:UIControlStateNormal]; [btn setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; [btn addTarget:self action:@selector (clickSingle) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:btn];} / / click the button to stop the call - (void) clickSingle{testSingle *single = [testSingle shareInstance]; NSLog (@ "% @", single);}

Console print results:

2017-02-23 18:38:05.637 pThreadTest[3368:314898] init the testSingle 2017-02-23 18:38:05.637 pThreadTest[3368:314898] < testSingle: 0x600000000d60> 2017-02-23; 18:38:06.437 pThreadTest[3368:314898] < testSingle: 0x600000000d60> 2017-02-23; 18:38:07.013 pThreadTest[3368:314898] < testSingle: 0x600000000d60> 2017-02-23; 18:38:07.317 pThreadTest[3368:314898] < testSingle: 0x600000000d60> 2017-02-23; 18:38:07.509 pThreadTest[3368:314898] < testSingle: 0x600000000d60> / / by the print results show that testSingle has only been initialized once, and only have a an example.

If we want to make a piece of code only once in the entire life cycle of the application, we can also use GCD to limit:
code:

Static dispatch_once_t onceToken; dispatch_once (& onceToken, NSLog ^{(@ "excute only once");});

Delayed execution of GCD:
drawback: cannot be cancelled.

- (void) clickDelayExecute{NSLog (@ --begin--); dispatch_after (dispatch_time (DISPATCH_TIME_NOW (int64_t) (2 * NSEC_PER_SEC)), dispatch_get_main_queue (NSLog), ^{(@ "delay execute");}});

Console print results:

2017-02-23 18:55:03.120 pThreadTest[3436:326559] --begin-- 2017-02-23 18:55:05.299 pThreadTest[3436:326559] delay execute / / start time: 18:55:03.120 execution time: 18:55:05.299

Four, multi-threaded NSOperation

NSOperation is a package of GCD, which encapsulates the operations that need to be performed, and the data needed to perform the operation, and can be executed in a concurrent or non concurrent form.
two use:
1, NSInvovationOperation& NSBlockOperation
, custom class inheritance NSOperation

Related concepts:
1, NSOperationQueue
a, thread pool queue, addOperation will join the thread
thread pool B, setMaxConcurrentOperationCount set the thread pool at the same time the maximum number of threads
2, ready, cancelled, executing
, finished, asynchronous (concurrent or non concurrent)
3, on -addDependency

Nonsense, on the code:

//NSInvocationOperation - (void) NSOperationTest{NSInvocationOperation *operation [[NSInvocationOperation alloc] initWithTarget:self = selector:@selector (invocationAction) object:nil]; [operation start];} - (void) invocationAction{NSLog (@ main thread%@ ", [NSThread currentThread] for (int); I = 0; I < =3; I + +) {[NSThread sleepForTimeInterval:1]; NSLog (@%d in" I, [NSThread, thread% @ currentThread]);}}

Console printing:

2017-02-23 19:17:00.487 pThreadTest[3498:342096] main thread< NSThread: 0x60000007ee80> {number = 1, name = main} 2017-02-23 19:17:01.489 pThreadTest[3498:342096] 0 in < NSThread: 0x60000007ee80> thread; {number = 1, name = main} 2017-02-23 19:17:02.490 pThreadTest[3498:342096] 1 in < NSThread: 0x60000007ee80> thread; {number = 1, name = main} 2017-02-23 19:17:03.491 pThreadTest[3498:342096] 2 in < NSThread: 0x60000007ee80> {number threads; = 1, name = main} 2017-02-23 19:17:04.493 pThreadTest[3498:342096] 3 in < NSThread: 0x60000007ee80> thread; {number = 1, name = main} / NSInvocationOperation operation is executed on the main thread
- (void) NSOperationTest{/ / NSBlockOperation NSLog (@ main thread%@ ", [NSThread currentThread]); NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{for (int i = 0; I < =3; I + +) {[NSThread sleepForTimeInterval:1]; NSLog (@%d in I, [NSThread thread% @", currentThread]);}}]; [blockOperation start]};

Console printing:

2017-02-23 19:25:09.868 pThreadTest[3524:346135] main thread< NSThread: 0x608000071800> {number = 1, name = main} 2017-02-23 19:25:10.870 pThreadTest[3524:346135] 0 in < NSThread: 0x608000071800> thread; {number = 1, name = main} 2017-02-23 19:25:11.871 pThreadTest[3524:346135] 1 in < NSThread: 0x608000071800> thread; {number = 1, name = main} 2017-02-23 19:25:12.872 pThreadTest[3524:346135] 2 in < NSThread: 0x608000071800> {number threads; = 1, name = main} 2017-02-23 19:25:13.874 pThreadTest[3524:346135] 3 in < NSThread: 0x608000071800> thread; {number = 1, name = main} / NSBlockOperation operation is executed on the main thread

The above two ways are to create the operation in the main thread, then NSOperation how to use asynchronous thread? Here on the use of the NSOperationQueue:
code:

@property (nonatomic, strong) - NSOperationQueue *queue; (void) NSOperationTest{NSLog (@ main thread%@ ", [NSThread currentThread]); NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{for (int i = 0; I < =3; I + +) {[NSThread sleepForTimeInterval:1]; NSLog (@%d in the thread, I, [NSThread currentThread]% @"}]);}; if (! Self.queue) {self.queue = [[NSOperationQueue alloc] init] [self.queue addOperation:blockOperation];}; NSLog (@ end);}

Console printing:

2017-02-23 19:30:25.969 pThreadTest[3543:350315] main thread< NSThread: 0x608000072600> {number = 1, name = main} 2017-02-23 19:30:25.970 pThreadTest[3543:350315] end 2017-02-23 19:30:27.042 pThreadTest[3543:350428] 0 in < NSThread: 0x60800007b140> thread; {number = 3, name = 2017-02-23 19:30:28.114 (null)} pThreadTest[3543:350428] 1 in < NSThread: 0x60800007b140> thread; {number = 3, name = 2017-02-23 19:30:29.183 (null)} pThreadTest[3543:350428] 2 in < NSThread: 0x60800007b140> thread; {number = 3, name = 2017-02-23 19:30:30.228 (null)} pThreadTest[3543:350428] 3 in < NSThread: 0x60800007b140> thread; {number = 3, name = //end (null)} first execution, instructions are executed asynchronously, thread encoding different description is in thread.

NSOperation custom:
code:

/ / / / customOperation.h / / pThreadTest / / Created / / by Dustin on 17/2/23. Copyright Dustin. All rights of 2017 / / reserved. / / #import < UIKit/UIKit.h> @interface; customOperation: NSOperation - (instancetype) initWithName: (NSString * name); / / @end / / customOperation.m / / pThreadTest / / Created / / by Dustin on 17/2/23. Copyright Dustin. All rights of 2017 / / reserved. / / #import "customOperation.h" @interface (customOperation) @property (nonatomic, copy) NSString * operName; @end @implementation customOperation (instancetype) initWithName: (NSString * name{) if (self = [super init]) {self.operName = name;} return self;} / / to override the main method - (void) main{for (int i = 0; I < I) {+ + 3; NSLog (@ "% @%d, self.operName, I); [NSThread sleepForTimeInterval:1];}} / / @end / / ViewController.m - (void) NSOperationTest{NSLog (@ main thread%@, [NSThread currentThread]"); if (! Self.queue) {self.queue = "NSOperationQueue alloc] init]; customOperation *customA [[customOperation alloc] initWithName:@} =" customA "]; [self.queue addOperation:customA]; NSLog (@ end);}

Console print results:

2017-02-23 19:51:03.284 pThreadTest[3621:365709] main thread< NSThread: 0x600000263a80> {number = 1, name = main} 2017-02-23 19:51:03.285 pThreadTest[3621:365709] end 2017-02-23 19:51:03.285 pThreadTest[3621:365846] customA 0 2017-02-23 19:51: 4.359 pThreadTest[3621:365846] customA 1 2017-02-23 19:51:05.433 pThreadTest[3621:365846] customA 2 / / results can be seen by the print operation, is the implementation of different steps in the thread

Set the maximum number of threads at the same time the thread pool:
code:

/ / / / customOperation.h / / pThreadTest / / Created / / by Dustin on 17/2/23. Copyright Dustin. All rights of 2017 / / reserved. / / #import < UIKit/UIKit.h> @interface; customOperation: NSOperation - (instancetype) initWithName: (NSString * name); / / @end / / customOperation.m / / pThreadTest / / Created / / by Dustin on 17/2/23. Copyright Dustin. All rights of 2017 / / reserved. / / #import "customOperation.h" @interface (customOperation) @property (nonatomic, copy) NSString * operName; @end @implementation customOperation (instancetype) initWithName: (NSString * name{) if (self = [super init]) {self.operName = name;} return self;} / / to override the main method - (void) main{for (int i = 0; I < I) {+ + 3; NSLog (@ "% @%d, self.operName, I); [NSThread sleepForTimeInterval:1];}} / / @end / / ViewController.m - (void) NSOperationTest{NSLog (@ main thread%@, [NSThread currentThread]"); if (! Self.queue) {self.queue = "NSOperationQueue alloc] init];} / / set the thread pool and the maximum number of threads [self.queue setMaxConcurrentOperationCount:1]; customOperation *customA = [[customOperation alloc] initWithName:@" customA "]; customOperation *customB = [[customOperation alloc] initWithName:@" customB "]; customOperation *customC = [[customOperation alloc] initWithName:@" customC "]; customOperation *customD = [[customOperation alloc] initWithName:@" customD "]; [self.queue addOperation:customA]; [self.queue addOperation:customB]; [self.queue addOperation:customC]; [self.queue addOperation:customD]; NSLog (@ end);}

Console print results:
when [self.queue setMaxConcurrentOperationCount:1];

2017-02-23 19:54:44.725 pThreadTest[3647:367833] main thread< NSThread: 0x600000076e80> {number = 1, name = main} 2017-02-23 19:54:44.726 pThreadTest[3647:367833] end 2017-02-23 19:54:44.726 pThreadTest[3647:368602] customA 0 2017-02-23 19:54: 45.800 pThreadTest[3647:368602] customA 1 2017-02-23 19:54:46.809 pThreadTest[3647:368602] customA 2 2017-02-23 19:54:47.882 pThreadTest[3647:368610] customB 0 2017-02-23 19:54:48.957 pThreadTest[3647:368610] customB 19:54:50.028 pThreadTest[3647:368610] 1 2017-02-23 customB 2 2017-02-23 19:54:51.098 pThreadTest[3647:368602] customC 0 2017-02-23 19:54:52.172 pThreadTest[3647:368602] customC 1 2017-02-23 19:54:53.241 pThreadTest[3647:368602] customC 2 2017-02-23 19:54:54.308 pThreadTest[3647:368610 0 2017-02-23 19:54:55.379 pThreadTest[3647:368610] customD customD 2017-02-23 19:54:56.451 pThreadTest[3647:368610] 1 customD 2 / 1 when the maximum number of threads are executed in sequence

When [self.queue setMaxConcurrentOperationCount:3]; when

2017-02-23 19:56:05.337 pThreadTest[3662:369743] main thread< NSThread: 0x600000070740> {number = 1, name = main} 2017-02-23 19:56:05.337 pThreadTest[3662:369743] end 2017-02-23 19:56:05.338 pThreadTest[3662:369819] customB 0 2017-02-23 19:56: 5.338 pThreadTest[3662:369789] customA 0 2017-02-23 19:56:05.338 pThreadTest[3662:369792] customC 0 2017-02-23 19:56:06.413 pThreadTest[3662:369792] customC 1 2017-02-23 19:56:06.413 pThreadTest[3662:369819] customB 19:56:06.413 pThreadTest[3662:369789] 1 2017-02-23 customA 1 2017-02-23 19:56:07.485 pThreadTest[3662:369792] customC 2 2017-02-23 19:56:07.485 pThreadTest[3662:369819] customB 2 2017-02-23 19:56:07.485 pThreadTest[3662:369789] customA 2 2017-02-23 19:56:08.561 pThreadTest[3662:369790 0 2017-02-23 19:56:09.635 pThreadTest[3662:369790] customD customD 2017-02-23 19:56:10.709 pThreadTest[3662:369790] 1 customD 2 / 3 when the maximum number of threads on the parallel execution

Set the code on the interdependence between
NSOperation:

/ / / / ViewController.m - (void) NSOperationTest{NSLog (@ main thread%@, [NSThread currentThread] "); if (self.queue! = [[NSOperationQueue) {self.queue alloc] init]}; / / set the thread pool and the maximum number of threads [self.queue setMaxConcurrentOperationCount:3]; customOperation *customA = [[customOperation alloc] initWithName:@" customA "]; customOperation *customB = [[customOperation alloc] initWithName:@" customB "customOperation *customC = [[customOperation; alloc] initWithName:@" customC "]; customOperation *customD = [[customOperation alloc] initWithName:@" customD "]; / / [customD addDependency:customA] to add a dependency between the operation; [customA addDependency:customC]; [customC addDependency:cu StomB]; / / it can or will / / [customB addDependency:customD] [self.queue addOperation:customA] deadlock;; [self.queue addOperation:customB]; [self.queue addOperation:customC]; [self.queue addOperation:customD]; NSLog (@ end);}

Console print results:

2017-02-23 20:01:51.687 pThreadTest[3701:374279] main thread< NSThread: 0x600000066180> {number = 1, name = main} 2017-02-23 20:01:51.688 pThreadTest[3701:374279] end 2017-02-23 20:01:51.688 pThreadTest[3701:374318] customB 0 2017-02-23 20:01: 52.740 pThreadTest[3701:374318] customB 1 2017-02-23 20:01:53.808 pThreadTest[3701:374318] customB 2 2017-02-23 20:01:54.884 pThreadTest[3701:374321] customC 0 2017-02-23 20:01:55.951 pThreadTest[3701:374321] customC 20:01:57.025 pThreadTest[3701:374321] 1 2017-02-23 customC 2 2017-02-23 20:01:58.026 pThreadTest[3701:374321] customA 0 2017-02-23 20:01:59.100 pThreadTest[3701:374321] customA 1 2017-02-23 20:02:00.101 pThreadTest[3701:374321] customA 2 2017-02-23 20:02:01.172 pThreadTest[3701:374318 CustomD 0 2017-02-23 pThreadTest[3701:374318] customD 2017-02-23 20:02:03.231 pThreadTest[3701:374318] customD 2 (20:02:02.230 1)

When the custom NSOperation add dependency, and operation add asynchronous operation:
code:

/ / / / customOperation.h / / pThreadTest / / Created / / by Dustin on 17/2/23. Copyright Dustin. All rights of 2017 / / reserved. / / #import < UIKit/UIKit.h> @interface; customOperation: NSOperation - (instancetype) initWithName: (NSString * name); / / @end / / customOperation.m / / pThreadTest / / Created / / by Dustin on 17/2/23. Copyright Dustin. All rights of 2017 / / reserved. / / #import "customOperation.h" @interface (customOperation) @property (nonatomic, copy) NSString * operName; @end @implementation customOperation (instancetype) initWithName: (NSString * name{) if (self = [super init]) {self.operName = name;} return self;} / / to override the main method - (void) main{/ for (int i = 0; I < I) {/ / 3 + +; NSLog (@ "% @%d, self.operName, I); / / [NSThread / / sleepForTimeInterval:1];} dispatch_async (dispatch_get_global_queue (0, 0), ^{[NSThread sleepForTimeInterval:1]; if (self.cancelled) {return}; NSLog (@"% @ ", self.operName);});} / / / / ViewController.m - (void) NSOperationTest{(NSLog" main thread%@ ", [NSThread @ currentThread]); if (self.queue! = [[NSOperationQueue) {self.queue alloc] init]}; / / set the thread pool and the maximum number of threads [self.queue setMaxConcurrentOperationCount:3]; customOperation *customA = [[customOperation alloc] initWithName:@" customA "]; customOperation *customB = [[customOperation alloc] initWithName:@" customB "]; CustomOperation *customC = [[customOperation alloc] initWithName:@ "customC"]; customOperation *customD = [[customOperation alloc] initWithName:@ "customD"]; [customD addDependency:customA]; [customA addDependency:customC]; [customC addDependency:customB]; / / it can or will / / [customB addDependency:customD] [self.queue addOperation:customA] deadlock;; [self.queue addOperation:customB]; [self.queue addOperation:customC]; [self.queue addOperation:customD]; NSLog (@ end);}

Console print results:

2017-02-23 20:08:05.766 pThreadTest[3722:378340] main thread< NSThread: 0x600000079180> {number = 1, name = main} 2017-02-23 20:08:05.767 pThreadTest[3722:378340] end 2017-02-23 20:08:06.841 pThreadTest[3722:378589] customB 2017-02-23 20:08: customD 2017-02-23 20:08:06.841 pThreadTest[3722:378591] 6.841 pThreadTest[3722:378624] customA 2017-02-23 20:08:06.841 pThreadTest[3722:378588] customC / / operation does not perform in accordance with the B C A D sequence, this is because the main function in the print operation is put in execution in the asynchronous thread.

Solve the above problems:

/ / / / customOperation.m / / pThreadTest / / Created / / by Dustin on 17/2/23. Copyright Dustin. All rights of 2017 / / reserved. / / #import "customOperation.h" @interface (customOperation) @property (nonatomic, copy) NSString *operName; @ property (nonatomic, assign) BOOL over; @end @implementation customOperation (instancetype) initWithName: (NSString * name{if (self) = [super init]) {self.operName = name;} return self;} / / to override the main method - (void) main{/ for (int i = 0; I < 3; I (+ +) {/ / NSLog @ "% @%d, self.operName, I); / / [NSThread / / sleepForTimeInterval:1];} / / asynchronous time the operation of dispatch_async (dispatch_get_global_queue (0, 0), [NSThread sleepForTimeInterval:1] ^{; If (self.cancelled) {return}; NSLog (@ "% @", self.operName); self.over = YES;}); / / keep using runloop thread while is not at the end of not executed when (self.over & &!! self.cancelled) {[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]] @end;}}

Console print results:

2017-02-23 20:16:01.330 pThreadTest[3744:384234] main thread< NSThread: 0x60800007c140> {number = 1, name = main} 2017-02-23 20:16:01.330 pThreadTest[3744:384234] end 2017-02-23 20:16:02.394 pThreadTest[3744:384384] customB 2017-02-23 20:16: customC 2017-02-23 20:16:04.535 pThreadTest[3744:384384] 3.459 pThreadTest[3744:384383] customA 2017-02-23 20:16:05.574 pThreadTest[3744:384386] customD / / so dependent on the order on the right

About Runloop here do not introduce too much, you can see some information from the internet.

Summary: on the multi thread for the time being summed up here, where I am not accurate enough to write or omissions, but also see a lot of friends exchange.