iOS multi thread four: NSThread + summary

Keywords: network Windows iOS Swift

 

1, NSThread

It is a lightweight Multithread in iOS. One NSThread object corresponds to one thread

1. Some class methods

[NSThread mainThread]; // Get main thread
[NSThread currentThread]; // Get current thread
// Blocking the current thread and setting the sleep time are implemented in two ways:
[NSThread sleepForTimeInterval:3];
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:3]];
[NSThread exit]; // Immediately terminate all threads except the main thread (including those executing tasks)
// Note: this method needs to be called with all thread states under control, otherwise it may cause memory problems.
//   threadPriority related are disabled, use qualityofservice (enumeration) instead
[NSThread threadPriority]; // Get current thread priority
[NSThread setThreadPriority:0.5]; // Set priority: 0.0 ~ 1.0; 1.0 has the highest priority

2. How to create

(1) , alloc init, but it needs to be opened manually

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(network:) object:@{@"name":@"moxiaohui"}];
[thread start];

[thread setName:@"moxiaoyan"]; // Thread name
thread.qualityOfService = NSQualityOfServiceUserInteractive;
//  NSQualityOfServiceUserInteractive = 0x21, / / highest priority for UI related tasks
//  NSQualityOfServiceUserInitiated = 0x19, / / second highest priority, used to perform tasks requiring immediate return
//  NSQualityOfServiceUtility = 0x11, / / normal priority, mainly used for tasks that do not need to return immediately
//  NSQualityOfServiceBackground = 0x09, / / background priority, which is used to handle tasks that are not perceived by users
//  NSQualityOfServiceDefault = -1 / / the default priority. When the priority is not set, the thread default priority
thread.stackSize = 8192; // Change stack size: must be a multiple of 4KB(1024) & & set before starting a thread (it will cost to create a thread)
NSUInteger size = thread.stackSize / 1024; // Memory occupied
[thread cancel]; // I won't quit right away. I made a mark to quit
[thread isMainThread];  // Is it the main thread
[thread isFinished];  // Has it been completed
[thread isCancelled]; // Has it been cancelled
[thread isExecuting]; // Is execution in progress


- (void)network:(NSDictionary *)info {
  NSLog(@"implement %@", [NSThread currentThread]);
  NSLog(@"info: %@", info);
  sleep(2);
  NSLog(@"complete");
}

(2) Initialization of a sub thread, feature: auto start, class method

@autoreleasepool {
  [NSThread detachNewThreadSelector:@selector(network:) toTarget:self withObject:@{@"name":@"moxiaohui"}];
}

(3) , implicit creation

// Execution in child threads: (time consuming operation)
[self performSelectorInBackground:@selector(network:) withObject:@{@"name":@"moxiaohui"}];
// In the main thread: (performing operations such as updating UI)
[self performSelectorOnMainThread:@selector(complete) withObject:nil waitUntilDone:YES];
// Execute in specified thread
[self performSelector:@selector(complete) onThread:[NSThread mainThread] withObject:@{@"name":@"moxiaohui"} waitUntilDone:YES];
// Execute in current thread
[self performSelector:@selector(network:) withObject:@{@"name":@"moxiaohui"}];
[self performSelector:@selector(network:) withObject:@{@"name":@"moxiaoyan"} withObject:@{@"name":@"moxiaohui"}];
[self performSelector:@selector(afterDelay:) withObject:@{@"name":@"moxiaoyan"} afterDelay:5]; // After 5s execution
// cancel a method
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(afterDelay:) object:@{@"name":@"moxiaoyan"}];
// cancel all the perform methods of the current object
[NSObject cancelPreviousPerformRequestsWithTarget:self];


- (void)afterDelay:(NSDictionary *)info {
  NSLog(@"afterDelay info:%@", info);
}

- (void)complete {
  NSLog(@"Update UI");
}

2, Need to lock manually (thread synchronization) (disadvantage)

A lot of examples are given by gods. Let me use them for reference: in the case of buying tickets through multiple windows, without locks, the data will be disordered

#pragma mark - multi window ticket
- (void)MultiWindowTicket {
  self.totalTicketCount = 20;
  _thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
  _thread1.name = @"Window 1";
  _thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
  _thread2.name = @"Window 2";
  _thread3 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
  _thread3.name = @"Window 3";
  [_thread1 start];
  [_thread2 start];
  [_thread3 start];
}

- (void)saleTicket {
  while (YES) { // The simulation will continue to operate with tickets
//    @synchronized (self) {/ / mutex: swift uses objc sync enter (self) and objc sync exit (self)
      if (self.totalTicketCount > 0) {
        self.totalTicketCount--;
        NSLog(@"I bought one, and there are still:%ld %@", (long)self.totalTicketCount, [NSThread currentThread]);
        [NSThread sleepForTimeInterval:0.5];
      } else {
        NSLog(@"The tickets are sold out.");
        break;
      }
//    }
  }
}
// Execution result:
// I bought one, and there are still: 7 < nsthread: 0x600003a41a00 > {number = 7, name = window 1}
// Bought one, and there are: 5 < nsthread: 0x600003a41a80 > {number = 9, name = window 3}
// I bought one, and left: 6 < nsthread: 0x600003a41a40 > {number = 8, name = window 2}
// Bought one, and there are: 3 < nsthread: 0x600003a41a40 > {number = 8, name = window 2}
// I bought one, and left: 4 < nsthread: 0x600003a41a80 > {number = 9, name = window 3}
// I bought one, and left: 4 < nsthread: 0x600003a41a00 > {number = 7, name = window 1}
// Bought one, and there are: 2 < nsthread: 0x600003a41a40 > {number = 8, name = window 2}
// I bought one, and there are: 2 < nsthread: 0x600003a41a80 > {number = 9, name = window 3}
// I bought one, and there are: 1 < nsthread: 0x600003a41a00 > {number = 7, name = window 1}
// I bought one, and there are: 0 < nsthread: 0x600003a41a40 > {number = 8, name = window 2}
// When the ticket is sold out < nsthread: 0x600003a41a80 > {number = 9, name = window 3}
// When the ticket is purchased < nsthread: 0x600003a41a00 > {number = 7, name = window 1}
// When the ticket is sold out < nsthread: 0x600003a41a40 > {number = 8, name = window 2}

From the execution result, it can be seen that there will be multiple windows, after selling a ticket, the remaining votes settled will be the same (that is, they sold the same ticket to multiple people)

Therefore, NSThread is not thread safe. It needs to be manually locked by program apes to keep thread synchronization!!!

 

3, Multithreaded summary

Three kinds of multithreading comparison
  GCD NSOperation NSThread
Realization C OC OC (Pthread based on C implementation)
life cycle

Automatic management

Automatic management

Program management

Lightweight grade in heavy light
performance high in low
Other Simple code combined with Block

More practical functions

(e.g. sequence setting, cancel at any time...)

Easy to use (no need to make too many settings),

More intuitive manipulation of Thread objects

    Object-oriented Object-oriented

 

 

 

 

 

 

 

 

 

54 original articles published, praised 13, visited 70000+
Private letter follow

Posted by pjsteinfort on Sun, 19 Jan 2020 05:42:32 -0800