Three ways to use multithreaded and multi-threaded implementations in IOS _ios

Source: Internet
Author: User
Tags gcd posix

Multithreading is a relatively lightweight way to implement multiple code execution paths within a single application.

At the system level, programs are executed side-by-day, and the program's execution time is determined based on the time required for the program and the time required by other programs.

However, within each program, there is one or more execution threads, which perform different tasks at the same time or in a way that occurs almost simultaneously.

Summary tip:

The threads in the iphone are not uncontrolled, according to official data, the stack size of the main thread on the iphone OS is 1M, the second thread starts with 512KB, and the value cannot be changed through compiler switches or thread API functions, only the main thread has the ability to modify the UI directly

First, thread overview

Some programs are a straight line, starting from the end--such as the simple Hello World, run out of print, its life cycle is over, like a flash in the pan.

Some programs are a circle that loops until it is cut off--like an operating system--running until you turn it off.

A running program is a process or a task, a process that contains at least one thread, and a thread is the execution flow of a program.

A program in Mac and iOS starts, creating a process in which a thread begins to function, which is called the main thread. The main line in the program is different from the other threads, it is the end of other threads of the parent thread, and all the interface display operation that is AppKit or uikit operation must be done in the main thread.

Each process in the system has its own virtual memory space, while multiple threads in the same process have the memory space of the common process.

Each creation of a new feed requires some memory (such as each thread has its own stack space) and consumes a certain amount of CPU time.

Thread safety issues need to be noted when multiple incoming pairs compete for the same resource

Creating Threads

Creating a new thread is adding an execution stream to the process, so a new thread needs to provide a function or method to import the thread.

1. Use of Nsthread

Nsthread provides the path to creating a thread, and it provides two ways to monitor whether the current thread is the main thread by using Nsthread to create a new thread:

1. Create a Nsthread object, invoke the Start method-Initialize a Nsthread object with a method of a target object, or create a subclass that inherits from Nsthread to implement the Main method? , and then directly create the object for this subclass.

2. Use DetachNewThreadSelector:toTarget:withObject: This class method creates a child thread, which is straightforward, using the target object's method directly as the thread launch portal

2. Use of NSObject

Using NSObject directly adds support for multithreading, allowing a method of an object to run in the background.

[MY0BJ performselectorinbackground: @selector (dosomething) Withobject:nil];

3.POSIX Thread

Since both Mac and iOS are based on the Darwin system, the Unx kernel of the Darwin system is based on Mach and BSD and inherits the BSD POSIX interface, so it is possible to open implementation threads directly using the POSIX thread-related interfaces
The interface for creating a thread is pthread_create, of course, before creating a thread you can create a property of the associated thread

——————————————————————————————————————

Nsoperation&nsoperationqueue

Many times we use multithreading, we need to control the number of concurrent threads, after all, threads also need to consume system resources, when the program running at the same time too many threads, the system will inevitably slow, so many times we control the number of simultaneous running threads
Nsoperation can encapsulate our operations, then put the created Nsoperation object into the Nsoperationqueue queue, and Operationqueue start a new thread to execute the operation in the queue. The number of concurrent operationqueue can be set in the following ways:

-(void) Setmaxconcurrentoperationcount: (Nsinteger) Count

GCD, the Grand-Dispatch acronym, is a series of BSD-level interfaces. The implementation of multithreading that was introduced after mac10.6 and IOS4.0 and now Nsoperation and Nsoperationqueue is based on GCD. This feature has also been ported to FreeBSD and can be viewed as an Open-source project for Libdispatch.

dispatch_queue_t imagedownloadqueue = dispatch_get_global_queue (dispatch_queue_priority_default, 0);

Of course, GCD in addition to processing multithreading there are many very good functions, it is based on a strong kqueue, efficiency can also be guaranteed.

Objective

In the multithreaded introduction, I've already explained that in order to improve the smoothness of the interface and the user experience. It is important that you do not block the main thread by putting time-consuming operations into other threads.

The following small series to bring you three kinds of iOS multithreaded programming methods:

Nsthread
Grand centeral Dispatch (GCD)
Nsoperation and Nsoperationqueue

1.NSThread

This is the most lightweight multithreaded approach, using the most intuitive multithreaded programming method. But because you need to manage the lifecycle of the thread yourself, thread synchronization. Nsthread is often used for debugging and is not recommended in actual projects.

Gets the current thread
nsthread *current = [Nsthread CurrentThread];
Gets the main thread
nsthread *main = [Nsthread mainthread];
NSLog (@ "Thread---%@", current);
NSLog (@ "Main thread---%@", main);

Console output Results:

2015-11-22 22:30:29.572 multi-threaded demo[1289:2925847] current thread---<nsthread:0x7fc0e1401dc0>{number = 1, name = main}
2015-11-22 22:30:29.572 multi-threaded demo[1289:2925847] Main thread---<nsthread:0x7fc0e1401dc0>{number = 1, name = main}

From the result we see that the current thread is the main one, number is the ID of the thread, name is the thread, and the number of the primary thread is 1

Blocking Threads:

Blocking thread 3 sec
[Nsthread sleepfortimeinterval:3];
[Nsthread sleepuntildate:[nsdate Datewithtimeintervalsincenow:3]];

2.GCD (Grand-Dispatch)

GCD is based on the C language API implementation of a set of multithreaded concurrency mechanism, very flexible and convenient, in the actual development of the use of a wide range.

Simply put, the CGD is to put the operation in the queue to execute.

All you have to do is define the operations and queues, and you don't need to directly control the thread's creation and destruction, and the thread's lifecycle is managed by the queue.

Queue: Responsible for the operation of the scheduling and implementation, with advanced first out (FIFO) characteristics. This means that the queue is first executed first, followed by the subsequent execution of the join.

There are two types of queues:

Serial queues:

The actions in the queue are executed sequentially, and you can imagine queues in a single window.

Parallel queues:

The actions in the queue may be executed concurrently, depending on the type of operation you can imagine as multiple window queues.

Create serial queue
dispatch_queue_t q = dispatch_queue_create ("My_serial_queue", dispatch_queue_serial);
Create parallel queues
dispatch_queue_t q = dispatch_queue_create ("My_concurrent_queue", dispatch_queue_concurrent);

My_serial_queue and My_concurrent_queue are the name tags of the queues, in order to differentiate with other queues, which must be unique within a project.

Dispatch_queue_serial represents a serial queue

Dispatch_queue_concurrent represents a parallel queue

There are also two types of operations:

Sync operation: Will only execute sequentially, the order of execution is OK.

Asynchronous operations: Order determination in serial queues, execution order indeterminate in parallel queues

Use block to define the code to be executed by the operation, Q is already defined, the queue to join

Define sync operation
Dispatch_sync (q, ^{
 //code to execute 
);
Define asynchronous Operation
Dispatch_async (q, ^{
 //code to execute  
);

Let's take a look at synchronization, asynchronous operations are added to the serial and parallel queues, the order and characteristics of execution: 1. The synchronization operation, regardless of the queue being added, is performed sequentially in the main thread

dispatch_queue_t q_serial = dispatch_queue_create ("My_serial_queue", dispatch_queue_serial);
dispatch_queue_t q_concurrent = dispatch_queue_create ("My_concurrent_queue", dispatch_queue_concurrent);
for (int i = 0; i < 5 ++i) {
 dispatch_sync (q_serial, ^{
 NSLog (@ "Sync task in serial queue%@%d", [Nsthread CurrentThread], i);
 }
for (int i = 0; i < 5 ++i) {
 dispatch_sync (q_concurrent, ^{
 NSLog (@ "Sync task in parallel queue%@%d", [Nsthread Currentthre AD], i);
 }

Here is the console output result:

2015-11-23 00:40:36.862 01.GCD Walkthrough [1952:3,613,752] synchronization task in serial queue <nsthread:0x7ff833505450>{number = 1, name = main} 0
2015-11-23 00:40:36.863 01.GCD Walkthrough [1952:3,613,752] synchronization task in serial queue <nsthread:0x7ff833505450>{number = 1, name = main} 1
2015-11-23 00:40:36.863 01.GCD Walkthrough [1952:3,613,752] synchronization task in serial queue <nsthread:0x7ff833505450>{number = 1, name = main} 2
2015-11-23 00:40:36.863 01.GCD Walkthrough [1952:3,613,752] synchronization task in serial queue <nsthread:0x7ff833505450>{number = 1, name = main} 3
2015-11-23 00:40:36.863 01.GCD Walkthrough [1952:3,613,752] synchronization task in serial queue <nsthread:0x7ff833505450>{number = 1, name = main} 4
2015-11-23 00:40:36.863 01.GCD Walkthrough [1952:3,613,752] synchronization task in parallel queue <nsthread:0x7ff833505450>{number = 1, name = main} 0
2015-11-23 00:40:36.863 01.GCD Walkthrough [1952:3,613,752] synchronization task in parallel queue <nsthread:0x7ff833505450>{number = 1, name = main} 1
2015-11-23 00:40:36.863 01.GCD Walkthrough [1952:3,613,752] synchronization task in parallel queue <nsthread:0x7ff833505450>{number = 1, name = main} 2
2015-11-23 00:40:36.864 01.GCD Walkthrough [1952:3,613,752] synchronization task in parallel queue <nsthread:0x7ff833505450>{number = 1, name = main} 3
2015-11-23 00:40:36.864 01.GCD Walkthrough [1952:3,613,752] synchronization task in parallel queue <nsthread:0x7ff833505450>{number = 1, name = main} 4

2. Asynchronous operations are performed only on threads that are not the main thread, and asynchronous operations in the serial queue are executed sequentially in the newly created thread.

 dispatch_queue_t q_serial = dispatch_queue_create ("My_serial_queue", dispatch_queue_serial);
 for (int i = 0; i < 5 ++i) {
  dispatch_async (q_serial, ^{
   NSLog (@ "Serial Queue--asynchronous task%@%d", [Nsthread CurrentThread], i);
  }
 

Because it is an asynchronous operation, a new thread is created. Because they are added to the serial queue, all operations are performed sequentially.

2015-11-23 01:03:22.372 01.GCD Walkthrough [2,081:3,627,139] serial Queue--Asynchronous Task <nsthread:0x7fb593d42f50>{number = 2, name = (null)} 0
2015-11-23 01:03:23.373 01.GCD Walkthrough [2,081:3,627,139] serial Queue--Asynchronous Task <nsthread:0x7fb593d42f50>{number = 2, name = (null)} 1
2015-11-23 01:03:24.374 01.GCD Walkthrough [2,081:3,627,139] serial Queue--Asynchronous Task <nsthread:0x7fb593d42f50>{number = 2, name = (null)} 2
2015-11-23 01:03:25.375 01.GCD Walkthrough [2,081:3,627,139] serial Queue--Asynchronous Task <nsthread:0x7fb593d42f50>{number = 2, name = (NULL)} 3
2015-11-23 01:03:26.376 01.GCD Walkthrough [2,081:3,627,139] serial Queue--Asynchronous Task <nsthread:0x7fb593d42f50>{number = 2, name = (NULL)} 4

3. Asynchronous operation, parallel queue

 dispatch_queue_t q_concurrent = dispatch_queue_create ("My_concurrent_queue", dispatch_queue_concurrent);
 for (int i = 0; i < 5 ++i) {
  dispatch_async (q_concurrent, ^{
   NSLog (@ "Parallel queue--asynchronous task%@%d", [Nsthread Currentthrea D], i);
  }
 

Theoretically, the parallel queue creates a new thread for each asynchronous operation and then lets all the tasks execute concurrently. But in fact the number of threads that the system can create is limited, and when the thread that is created reaches the maximum number of threads, subsequent asynchronous operations need to wait for the previous operation to complete before they are executed. Which thread operation completes, arranges the waiting asynchronous task to which thread. Until all operations have been completed. You can observe this phenomenon by changing the number of loops in the above code to 5000.

2015-11-23 01:14:15.282 01.GCD Walkthrough [2,165:3,634,728] parallel Queue--Asynchronous Task <nsthread:0x7fb3b841b0a0>{number = 4, name = (NULL)} 3
2015-11-23 01:14:15.282 01.GCD Walkthrough [2,165:3,634,724] parallel Queue--Asynchronous Task <nsthread:0x7fb3b8514da0>{number = 3, name = (null)} 0
2015-11-23 01:14:15.282 01.GCD Walkthrough [2,165:3,634,726] parallel Queue--Asynchronous Task <nsthread:0x7fb3b8604db0>{number = 5, name = (null)} 2
2015-11-23 01:14:15.282 01.GCD Walkthrough [2,165:3,634,725] parallel Queue--Asynchronous Task <nsthread:0x7fb3b86119d0>{number = 2, name = (null)} 1
2015-11-23 01:14:15.285 01.GCD Walkthrough [2,165:3,634,729] parallel Queue--Asynchronous Task <nsthread:0x7fb3b87011f0>{number = 6, name = (NULL)} 4

3.NSOperation & Nsoperationqueue

Although GCD is already powerful, the API it uses is still in C language. At some point, it is very inconvenient and unsafe to use in object-oriented objective-c.

So Apple abstracts the operations in GCD into Nsoperation objects, abstracting the queues as Nsoperationqueue objects.


Abstract for the benefit of Nsoperation & Nsoperationqueue after a few:

Code style Unified, we do not have to write in the object-oriented objective-c in the face of the process of the C language code.
We know that the execution code of the operation in GCD is written in the anonymous block, so it is difficult to set dependencies on the operation and cancel the operation. These features are already encapsulated within the Nsoperation object. ^-^
Nsoperationqueue objects are more powerful and flexible than queues in gcd, such as setting the number of concurrent operations and canceling all operations in the queue.
Nsoperation are divided into nsinvocationoperation and nsblockoperation

The use of nsinvocationoperation

First, define a Nsoperationqueue object
nsoperationqueue *queue = [[Nsoperationqueue alloc] init];
Nsinvocationoperation *op = [[Nsinvocationoperation alloc] initwithtarget:self selector: @selector (operationaction:) object:@ "Here can wear parameters"];
[Queue addoperation:op];//the operation into the queue
-(void) Operationaction: (id) obj
{
 NSLog (@ "%@-obj:%@", [ Nsthread CurrentThread], obj);

The output is:

2015-11-23 02:55:19.067 multi-threaded demo[2604:3686934] <nsthread:0x7f9dfa443510>{number = 2, name = (null)}-obj: You can wear parameters here

The use of nsblockoperation

Nsoperationqueue *queue = [[Nsoperationqueue alloc] init];
Nsblockoperation *op = [Nsblockoperation blockoperationwithblock:^{
 [self operationaction:@ "This is NSBlockOperation" ];
}];
[Queue Addoperation:op];

The output is:

2015-11-23 02:56:11.812 multi-threaded demo[2617:3687872] <nsthread:0x7fa983f10a50>{number = 2, name = (null)}-obj: This is Nsbloc Koperation

Set dependencies (Order of execution)

 Nsoperationqueue *queue = [[Nsoperationqueue alloc] init];
 Nsinvocationoperation *OP1 = [[Nsinvocationoperation alloc] initwithtarget:self selector: @selector (operationaction:) object:@ "OP1"];
 Nsinvocationoperation *OP2 = [[Nsinvocationoperation alloc] initwithtarget:self selector: @selector (operationaction:) object:@ "OP2"];
 OP2 after OP1
 [op2 adddependency:op1];//here need to be aware that you must set up a dependency relationship before addoperation 
 [queue addoperation:op1];
 [Queue ADDOPERATION:OP2];

The output is:

2015-11-23 02:57:40.283 multi-threaded demo[2661:3689737] <nsthread:0x7fb663e132d0>{number = 2, name = (null)}-OBJ:OP1
2015-11-23 02:57:40.284 multi-threaded demo[2661:3689737] <nsthread:0x7fb663e132d0>{number = 2, name = (null)}-OBJ:OP2

The output of the dependency is not set:

2015-11-23 03:00:45.939 multi-threaded demo[2709:3692307] <nsthread:0x7fe951d0d8a0>{number = 2, name = (null)}-OBJ:OP2
2015-11-23 03:00:45.939 multi-threaded demo[2709:3692308] <nsthread:0x7fe951c24720>{number = 3, name = (null)}-OBJ:OP1

Here you should find that, in Nsoperation & Nsoperationqueue, we do not need to define the type of operation and the type of queue and the order in which the operations are executed, but you just need to set the order of execution of the operation directly.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.