preface

In daily development, the use of multithreading can help us solve a lot of problems, such as the operation of a large amount of data, the execution of complex programs, and the use of locks to achieve some requirements, this series of articles mainly introduces the use of iOS multithreading technology.

IOS: Multithreading (1) — pthread

For the introduction and use of Pthreads, please refer to previous articles. This article focuses on NSThreads.

About the NSThread

NSThread is an object-oriented lightweight multithreading solution officially provided by Apple. An NSThread object represents a thread, requiring programmers to manually manage the life cycle of the thread and deal with thread synchronization.

NSThread use

Commonly used method

In daily development, we often use [NSThread currentThread] to get the currentThread, which is convenient for development and debugging. This is the most commonly used method. In addition, the following methods are also used frequently. Methods in the classification of NSThreadPerformAdditions based on NSObject can be easily called by subclasses that inherit from NSObject.

/ / the current thread to sleep to the appointed time [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 1.0]]. NSThread sleepForTimeInterval:1.0; // [NSThread callStackSymbols]return NSArray
    // [NSThread callStackReturnAddresses]   return NSArray
    NSLog(@"callStackSymbols : %@", [NSThread callStackSymbols]);
    NSLog(@"callStackReturnAddresses : %@", [NSThread callStackReturnAddresses]); @ interface NSObject (NSThreadPerformAdditions) / / specified method performs - (void) in the main thread aSelector performSelectorOnMainThread: (SEL) withObject:(nullable id)argwaitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait; Equivalent to the first method with kCFRunLoopCommonModes // specifies the method to be executed in a thread - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)argwaitUntilDone:(BOOL)waitModes :(nullable NSArray<NSString *> *)array API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0)); - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)argwaitUntilDone:(BOOL)waitAPI_AVAILABLE (macos (10.5), the ios (2.0), watchos (2.0), tvos (9.0)); // equivalent to the first method with kCFRunLoopCommonModes // Specifies that the method is executed in the open child thread (void) performSelectorInBackground aSelector: (SEL) withObject: (nullable id) arg API_AVAILABLE (macos (10.5), the ios (2.0), Tvos watchos (2.0), (9.0)); @endCopy the code

Create a thread

  • The instance method creates a thread

    The instance method creates a thread and can set parameters as needed, calling -start () to start the thread and calling -cancel () to cancel it

    // SEL
    NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(nsThreadMethod:) object:@"thread"]; NSThread *thread2 = [[NSThread alloc] init]; NSThread *thread3 = [[NSThread alloc] initWithBlock:^{NSLog(@)"Thread %s: %@", __func__, [NSThread currentThread]); }]; // Set the name thread1.name = @"thread1"; The value of the scheduling priority ranges from 0.0 to 1.0. The default value is 0.5. A larger value indicates a higher priority. Thread3. ThreadPriority = 0.0; // Start thread [thread1 start]; // Whether the thread is executingif ([thread3 isExecuting]) {
        NSLog(@"thread1 is executing! "); } // Cancel the thread [thread1 cancel]; // Whether to cancel the threadif ([thread1 isCancelled]) {
        NSLog(@"thread1 canceled!"); } // Whether the thread ends executionif ([thread3 isFinished]) {
        NSLog(@"thread3 is finished!");
    }
Copy the code
  • Class methods create threads

    Class methods do not need to call the start method to create nsThreads, and set parameters through class methods

/ / block way [NSThread detachNewThreadWithBlock: ^ {NSLog (@Class method block creates thread: %s: %@, __func__, [NSThread currentThread]); }]; // SEL [NSThread detachNewThreadSelector:@selector(nsThreadMethod:) toTarget:self withObject:nil]; /* [NSThread currentThread]; Threads [NSThread isMultiThreaded]; Whether the currently running thread code for the child thread * / / / the current thread to sleep to the appointed time [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 1.0]]. NSThread sleepForTimeInterval:1.0; Double priority = [NSThread threadPriority]; NSLog(@"Current thread priority: %f", priority);
    [NSThread setThreadPriority: 0.9];Copy the code

Interthread communication

Usually, if we have a network request that’s being executed in a child thread, and the request is successful and we need to go back to the main thread to refresh the UI, it’s time to understand the communication between the child thread and the main thread, and NSThread provides us with a solution, By calling the methods in the NSObject and NSObject (NSThreadPerformAdditions) categories, all instantiations that inherit from NSObject can call the following methods

/ / the specified method on the main thread that executes [self performSelectorOnMainThread: @ the selector (performMethod:) / / to execute method withObject: nil / / execution method, The parameter type to be passed is IDwaitUntilDone:YES]; // Whether the current thread should block until the main thread finishes executing the code block we specified. The current thread, the main thread, will execute immediately when set to YES. To NO when join the RunLoop execution when the next run cycle [self performSelectorOnMainThread: @ the selector (performMethod:) withObject: nilwaitUntilDone:YES
                                modes:@[@"kCFRunLoopDefaultMode"]]. - (void)performSelector:(SEL)aSelector onThread:(NSThread *) THR withObject:(nullable id)argwaitUntilDone:(BOOL)waitModes :(nullable NSArray<NSString *> *)array API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0)); - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)argwaitUntilDone:(BOOL)wait; // 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; / / specified method in open the child thread of execution (equivalent to create a child thread, and execution method) [self performSelectorInBackground: @ the selector (performMethod:) withObject: nil];Copy the code

As an example, let’s simulate the implementation of a network request successfully returning to a threaded refresh UI

/ / create a child thread simulation network request [NSThread detachNewThreadWithBlock: ^ {NSLog (@Class method block creates thread: %s: %@, __func__, [NSThread currentThread]); // Simulate network request time-consuming operationfor (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"Network request %@",[NSThread currentThread]);
        }
        
        NSLog(@"Network request successful ready to go back to main thread refresh UI %@",[NSThread currentThread]); / / main thread to refresh the UI [self performSelectorOnMainThread: @ the selector (mainThreadRefreshUI) withObject: nilwaitUntilDone:YES]; }]; // mainThreadRefreshUI - (void)mainThreadRefreshUI {NSLog(@)"Back to main thread and refresh UI %s: %@", __func__, [NSThread currentThread]);
}
Copy the code

The above is an introduction to NSThread and its simple usage. Please refer to relevant demo

Github.com/G-Jayson/Mu…