The advantages and disadvantages

1. Advantages: NSThread is more lightweight than the other two multithreading schemes and controls thread object 2 more intuitively. Disadvantages: need to manage their own thread life cycle, thread synchronization. Locking data for thread synchronization has some system overhead

Thread creation

// 1. Initialize the thread
// Selector: a method executed by a thread that takes at most one argument
// target: selector to which the message is sent
Argument: the unique argument passed to selector, which can also be nil
- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument;

// 2. Create and start a new thread
- (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;

// 3. Implicitly create and start threads
- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg;

// get the main thread
+ (NSThread *)mainThread;   

// 5. Get the current thread
+ (NSThread *)currentThread;
Copy the code

Thread state

Thread state changes refer to multithreading (I) processes and threads.

// Start the thread
// The thread enters the ready state -> running state. The thread enters the dead state automatically when the task is completed
- (void)start;

// block (pause) the thread method
// The thread is blocked
+ (void)sleepUntilDate:(NSDate *)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;

// Force the thread to stop
// The thread enters the dead state
+ (void)exit;
Copy the code
// 暂停2s
[NSThread sleepForTimeInterval:2];

/ / or
NSDate *date = [NSDate dateWithTimeInterval:2 sinceDate:[NSDate date]];
[NSThread sleepUntilDate:date];
Copy the code

Other methods

// Determine whether the thread is the master thread (object method)
- (BOOL)isMainThread;

// Determine whether the thread is the primary thread (class method)
+ (BOOL)isMainThread;    
	
// Thread name -- setter method
- (void)setName:(NSString *)n;    

// Set thread priority (0.0-1.0, 1.0 superlative)
- (void)setThreadPriority:(double)p;
Copy the code

Communication between threads

// 1. Perform operations on the main thread
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray<NSString *> *)array;
  // equivalent to the first method with kCFRunLoopCommonModes

// 2. Execute the operation on the specified thread
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array NS_AVAILABLE(10_5.2_0);
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5.2_0);

// 3. Perform the operation on the current thread, calling NSObject's performSelector: related method
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
Copy the code

Here is an example of downloading an image:

  1. Download images in the child thread;
  2. After downloading the image, call back to the main thread to refresh the view.
/** * Create a thread to download the image */
- (void)downloadImageOnSubThread {
    // Call downloadImage in the created child thread to download the image
    [NSThread detachNewThreadSelector:@selector(downloadImage) toTarget:self withObject:nil];
}

/** * Download the image and go back to the main thread to refresh the UI */
- (void)downloadImage {
    
    NSLog(@"current thread -- %@"[NSThread currentThread]);
    
    // 1. Get imageUrl
    NSURL *imageUrl = [NSURL URLWithString:@"https://wiki-1259056568.cos.ap-shanghai.myqcloud.com/ios/20190627101912.png"];
    
    // 2. Read data from imageUrl (download image) -- time consuming operation
    NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];
    // Create an image from binary data
    UIImage *image = [UIImage imageWithData:imageData];
    
    // 3. Go back to the main thread for image assignment and interface refresh
    [self performSelectorOnMainThread:@selector(refreshOnMainThread:) withObject:image waitUntilDone:YES];
}

/** * return to main thread for image assignment and interface refresh */
- (void)refreshOnMainThread:(UIImage *)image {
    NSLog(@"current thread -- %@"[NSThread currentThread]);
    
    // Assign the image to imageView
    self.imageView.image = image;
}
Copy the code

NSThread subclass

You can subclass NSThread and override the [the main] (https://developer.apple.com/documentation/foundation/nsthread/1418421-main) method to implement your thread ‘s main entry point. If you override [main](https://developer.apple.com/documentation/foundation/nsthread/1418421-main), you do not need to invoke the inherited behavior by calling super.

reference

link

  1. NSThread Reference