Multithreading basics in iOS development

Source: Internet
Author: User

Multithreading basics in iOS development
Time-consuming operation drill code walkthrough compilation time-consuming Method

- (void)longOperation {    for (int i = 0; i < 10000; ++i) {        NSLog(@"%@ %d", [NSThread currentThread], i);    }}
Call the time-consuming method directly
// 1> directly call the time-consuming method [self longOperation];

Running Test Results

How to execute time consumption in the background
// 2> run the time consumption method in the background [self defined mselectorinbackground: @ selector (longOperation) withObject: nil];

Running Test Results

Summary [NSThread currentThread]: Current thread object
It can be used in all multithreading technologies! Usually used in multi-thread development, whether the Log Code is running in the main thread number
number == 1Main thread number != 1The background thread should not tangle with the specific number pthread Drill pthreadYes POSIXMulti-threaded development framework, because it is a cross-platform C language framework, there is no detailed comment in the Apple header file for reference pthreadFor information, visit the http://baike.baidu.com to import header files
#import 
  
Pthread Drill
// Create a thread and execute the demo function-(void) pthreadDemo {/** parameter in the thread: 1> pointer to the thread identifier, in C, the end of the type is usually _ t/Ref, and you do not need to use * 2> to set the thread attribute 3> the start address of the thread running function 4> the return value of the parameter running function: -If the thread is successfully created, 0 is returned.-If the thread fails to be created, an error code */pthread_t threadId = NULL is returned. NSString * str = @ "Hello Pthread "; int result = pthread_create (& threadId, NULL, demo, (_ bridge void *) (str); if (result = 0) {NSLog (@ "create thread OK");} else {NSLog (@ "failed to create thread % d", result );}} // The background thread calls the void * demo (void * params) {NSString * str = (_ bridge NSString *) (params) function ); NSLog (@ "% @-% @", [NSThread currentThread], str); return NULL ;}
Summary in C language, no ObjectObject is StructNormally, in the C language framework, the object type is _t/RefAnd does not need to be used for declaration. * In Cvoid *And in OCidIs equivalentMemory Management
In OC, if it is ARCDuring compilation, the compiler automatically adds retain/ release/ autoreleaseHowever, ARCOnly responsible for management OCPart of the memory management, not responsible C LanguageTherefore, if you use CLanguage framework appearance retain/ create/ copy/ newMost of the functions require releaseOtherwise, memory leakage occurs during hybrid development. CAnd OCUse __bridgeBridge, BridgingThe purpose is to tell the compiler how to manage the addition of memory bridging. You can use Xcode's auxiliary functions to add MRCYou do not need to use bridging three methods to create a thread to prepare a function.
// MARK:-the backend thread calls the function-(void) longOperation :( id) obj {NSLog (@ "% @-% @", [NSThread currentThread], obj );}
1. alloc/init-start
// MARK:-NSThread drill-(void) threadDemo1 {// 1. instantiated thread object => alloc (memory allocation)/init (initialization) NSThread * t = [[NSThread alloc] initWithTarget: self selector: @ selector (longOperation :) object: @ "alloc/init"]; // 2. start thread [t start]; // 3. current thread? NSLog (@ "% @", [NSThread currentThread]);}
Drill Summary [t start];After execution, it will be executed in another thread demoMethod in OC, the code of any method is the code of the same method executed in the top-down order, and is executed in the same thread ( blockExcept) 2. detachNewThreadSelector
-(Void) threadDemo2 {// detach => Detach a subthread to execute demo: method [NSThread detachNewThreadSelector: @ selector (longOperation :) toTarget: self withObject: @ "detach"]; // 2. current thread? NSLog (@ "% @", [NSThread currentThread]);}
Drill Summary detachNewThreadSelectorClass method does not need to be started. After the thread is created, the thread is automatically started for execution. @selectorMethod 3. Classification Method
-(Void) threadDemo3 {// 1. Run the @ selector method [self defined mselectorinbackground: @ selector (longOperation :) withObject: @ "category"] in the background; // 2. What is the current thread? NSLog (@ "% @", [NSThread currentThread]);}
performSelectorInBackgroundYes NSObjectThe classification method of does not exist. threadIt will be executed in the background thread immediately @selectorMethod All NSObjectYou can use this method in other threads! Custom object Person class
// MARK:-Person class @ interface Person: NSObject // name @ property (nonatomic, copy) NSString * name; @ end @ implementation Person // use the dictionary to instantiate the object + (instancetype) personWithDict :( NSDictionary *) dict {Person * p = [[Person alloc] init]; [p setValuesForKeysWithDictionary: dict]; return p;} // load data-(void) loadData {NSLog (@ "load data %%%@", [NSThread currentThread], self. name) ;}@ end
Use the classification method for the Person class
- (void)threadDemo4 {    Person * p = [Person personWithDict:@{@"name": @"zhangsan"}];    [p performSelectorInBackground:@selector(loadData) withObject:nil];}
Thread status drill code
// MARK:-thread status drill-(void) statusDemo {NSLog (@ "Sleep"); [NSThread sleepForTimeInterval: 1.0]; for (int I = 0; I <20; ++ I) {if (I = 8) {NSLog (@ "Sleep"); [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 1.0];} NSLog (@ "% @ % d", [NSThread currentThread], I); if (I = 10) {NSLog (@ "88 "); [NSThread exit] ;}} NSLog (@ "Can you come? ");}
-(Void) touchesBegan :( NSSet *) touches withEvent :( UIEvent *) event {// do not call the exit method on the main thread // [NSThread exit]; // instantiate the thread object (new) NSThread * t = [[NSThread alloc] initWithTarget: self selector: @ selector (statusDemo) object: nil]; // The thread is ready (added to the scheduling thread pool) [t start];}
Blocking method execution process. When a certain condition is met, you can use sleepMethod To let the thread enter BlockingStatus

1>sleepForTimeInterval

From now on Seconds

2>sleepUntilDate

Sleep from now on to the specified date of death

[NSThread exit];

Once the thread is forcibly terminated, all subsequent code will not be executed. Note: Before terminating the thread, pay attention to releasing the previously allocated objects!Ready-> RUN

Thread slaveReadyAndRunSwitching between statuses is causedCPUResponsible, programmers cannot intervene

Thread property drill code
// MARK:-thread Attribute-(void) threadProperty {NSThread * t1 = [[NSThread alloc] initWithTarget: self selector: @ selector (demo) object: nil]; // 1. thread name t1.name = @ "Thread AAA"; // 2. priority t1.threadPriority = 0; [t1 start]; NSThread * t2 = [[NSThread alloc] initWithTarget: self selector: @ selector (demo) object: nil]; // 1. thread name t2.name = @ "Thread BBB"; // 2. priority t2.threadPriority = 1; [t2 start];}-(void) demo {fo R (int I = 0; I <10; ++ I) {// stack size NSLog (@ "% @ stack size: % tuK", [NSThread currentThread], [NSThread currentThread]. stackSize/1024);} // simulate the crash // determine whether it is the main thread // if (! [NSThread currentThread]. isMainThread) {// NSMutableArray * a = [NSMutableArray array]; // [a addObject: nil]; //}
Attribute 1. name-The thread name is in a large commercial project. Generally, when the program crashes, obtain the thread where the program runs accurately. 2. threadPriority-Thread priority, which is a floating point number with a value range from 0~1.0
1.0Highest priority 0.0Indicates that the lowest priority is 0.5The high priority only ensures the possibility of CPU scheduling. I personally suggest that you do not modify the priority of multi-thread during development. The goal is to put time-consuming operations in the background, the main thread and user interaction are not blocked! Multi-threaded development principles: simplicity 3. stackSize-Stack zone size: by default, whether it is the main thread or sub-thread, the stack zone size is 512KStack zone size can be set
[NSThread currentThread].stackSize = 1024 * 1024;
4. isMainThread-Whether to share resources in the main thread-Ticket Selling

Multi-threaded development is relatively complex. You can write code as follows during development:

First, make sure that a single thread executes the correct logic of adding a thread to sell tickets
-(Void) touchesBegan :( NSSet *) touches withEvent :( UIEvent *) event {self. tickets = 20; [self saleTickets];} // ticket selling logic-each ticket sales logic (window) should sell all tickets-(void) saleTickets {while (YES) {if (self. tickets> 0) {self. tickets --; NSLog (@ "remaining votes % d % @", self. tickets, [NSThread currentThread]);} else {NSLog (@ "no votes % @", [NSThread currentThread]); break ;}}}
Add thread
-(Void) touchesBegan :( NSSet *) touches withEvent :( UIEvent *) event {self. tickets = 20; NSThread * t1 = [[NSThread alloc] initWithTarget: self selector: @ selector (saleTickets) object: nil]; t1.name = @ "conductor "; [t1 start]; NSThread * t2 = [[NSThread alloc] initWithTarget: self selector: @ selector (saleTickets) object: nil]; t2.name = @ "conductor B "; [t2 start];}
Add sleep
-(Void) saleTickets {while (YES) {// simulate sleep [NSThread sleepForTimeInterval: 1.0]; if (self. tickets> 0) {self. tickets --; NSLog (@ "remaining votes % d % @", self. tickets, [NSThread currentThread]);} else {NSLog (@ "no votes % @", [NSThread currentThread]); break ;}}}

Test result

Add mutex lock
-(Void) saleTickets {while (YES) {// simulate sleep [NSThread sleepForTimeInterval: 1.0]; @ synchronized (self) {if (self. tickets> 0) {self. tickets --; NSLog (@ "remaining votes % d % @", self. tickets, [NSThread currentThread]);} else {NSLog (@ "no votes % @", [NSThread currentThread]); break ;}}}}
The mutex lock summary ensures that only one thread can execute the code in the lock at the same time! The lock range of the mutex should be as small as possible. The larger the lock range, the worse the efficiency! Stenography skills [[NSUserDefaults standardUserDefaults] synchronize];Any lock allowed by mutex lock Parameters NSObjectObject Note: The lock object must be accessible by all threads.If there is only one place in the code that requires locking, most of them use selfThis avoids the creation of another lock object atomic attribute (thread security). It is designed for multithreading and is the default attribute when multiple threads write atomic attributes (called setterTo ensure that only one thread executes write operations at a time. Single (thread) write multiple (thread) readMultithreading technology Atomic attributes are more efficient than mutex locks., But it may appear Dirty dataWhen defining attributes, you must specify nonatomicDrill code
@ Interface ViewController () @ property (atomic, strong) NSObject * obj1; @ property (atomic, strong) NSObject * obj2; @ end @ implementation ViewController @ synthesize obj1 = _ obj1; // atomic property simulation code // obj1-getter-(NSObject *) obj1 {return _ obj1;} // obj1-setter-(void) setObj1 :( NSObject *) obj1 {@ synchronized (self) {_ obj1 = obj1;}-(void) touchesBegan :( NSSet *) touches withEvent :( UIEvent *) event {long largeNumber = 1000*1000; // mutex lock test CFAbsoluteTime start = CFAbsoluteTimeGetCurrent (); for (int I = 0; I <largeNumber; ++ I) {self. obj1 = [[NSObject alloc] init];} NSLog (@ "% f", CFAbsoluteTimeGetCurrent ()-start); // spin lock Test start = CFAbsoluteTimeGetCurrent (); for (int I = 0; I <largeNumber; ++ I) {self. obj2 = [[NSObject alloc] init];} NSLog (@ "% f", CFAbsoluteTimeGetCurrent ()-start);} @ end

The internal lock of the atomic attribute isSpin lock,The execution efficiency of spin locks is higher than that of mutex locks.

Spin lock & mutex lock

Commonalities

Only one thread executes the Code with the lock range at the same time.

Differences

Mutex lock: If other threads are executing the locked code, the thread will Enter sleep statusWait until the execution of other threads is completed. After the lock is opened, the thread will be Wake up Spin lock: If other threads are executing the locked code, the thread will Endless loopWait until the lock code execution is complete.

Conclusion

The spin lock is more suitable for executing very short code. No matter what the lock is, it must pay the price. When multiple threads perform read/write operations, the correct results are still returned, known as thread security, to achieve thread security, it must be used LockFor better user experience, UIKit is NOT thread-safe

Convention: all operations to update the UI must be performed on the main thread!

Therefore, Main threadAlso known UI threadIt is recommended that all attributes be declared nonatomicAvoid multiple threads to snatch the same resource as much as possible. The business logic of locking and resource grabbing should be handed over to the server for processing, reducing the pressure on the mobile client. The main thread of Inter-thread communication must implement the defined attributes.
/// The root view is a rolling view @ property (nonatomic, strong) UIScrollView * scrollView; // The Image view @ property (nonatomic, weak) UIImageView * imageView; /// image downloaded over the network @ property (nonatomic, weak) UIImage * image;
LoadView

The role of the loadView method:

Loading view hierarchies using functions and Storyboard& XIBIs equivalent

If you overwriteloadView,Storyboard&XIBInvalid

- (void)loadView {    self.scrollView = [[UIScrollView alloc] init];    self.scrollView.backgroundColor = [UIColor orangeColor];    self.view = self.scrollView;    UIImageView *iv = [[UIImageView alloc] init];    [self.view addSubview:iv];    self.imageView = iv;}
After the viewDidLoad view is loaded, you can perform some data initialization. If you use code-only development, do not set the UI in this method.
-(Void) viewDidLoad {[super viewDidLoad]; // download the image [self downloadImage];}
Download network images
-(Void) downloadImage {// 1. network image resource path NSURL * url = [NSURL URLWithString: @ "http://c.hiphotos.baidu.com/image/pic/item/4afbfbedab64034f42b14da1aec379310a551d1c.jpg"]; // 2. instantiate binary data (Network Access) from the network resource path NSData * data = [NSData dataWithContentsOfURL: url]; // 3. convert binary data to image UIImage * image = [UIImage imageWithData: data]; // 4. set image self. image = image ;}
Set Images
-(Void) setImage :( UIImage *) image {// 1. set the image self in the Image view. imageView. image = image; // 2. set the size of the Image view according to the image size [self. imageView sizeToFit]; // 3. sets the contentSize self of the scroll view. scrollView. contentSize = image. size ;}
Set the zoom of the scroll View

1> set the zoom attribute of the scroll View

// 1> Minimum zooming ratio self. scrollView. minimumZoomScale = 0.5; // 2> maximum zoomscale self. scrollView. maximumZoomScale = 2.0; // 3> set proxy self. scrollView. delegate = self;

2> implement proxy-tell the scroll view which view is scaled

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {    return self.imageView;}

3> trackingscrollViewZoom Effect

- (void)scrollViewDidZoom:(UIScrollView *)scrollView {    NSLog(@"%@", NSStringFromCGAffineTransform(self.imageView.transform));}
Inter-thread communication downloads images in background threads
[self performSelectorInBackground:@selector(downloadImage) withObject:nil];
Set the image in the main thread
[self performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];}

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.