Thread definition (Employee)

  1. A thread is the basic execution unit of a process, in which all tasks of a process are executed
  2. In order for a process to perform a task, it must have threads, at least one thread
  3. By default, the program starts a thread, which is called the main thread or UI thread

Process Definition (Milk tea Shop)

  1. A process is an application that is running in the system
  2. Each process is independent of each other, and each process runs in its own dedicated and protected memory

The relationship and difference between threads and processes

  1. Address space: Threads of the same process share the address space of the same process, while processes are independent of each other.
  2. Resource ownership: Threads in the same process share resources of the same process, such as memory, I/O, and CPU, but resources between processes are independent
  3. The crash of one process in protected mode does not affect other processes, but the crash of one thread kills the whole process, so multi-process is more robust than multi-thread
  4. Process switchover consumes large resources and is efficient. So when it comes to frequent switching, it’s better to use threads than processes, and if you need concurrent operations that also share variables, you can only use threads rather than processes
  5. Execution process: Each independent process has a program run entry, sequential execution sequence, and program entry. However, threads cannot execute independently and must depend on the application, which provides multiple thread execution control
  6. Threads are the basic unit of processor scheduling, but processes are not

** Extension: ** Apple is a single process, sandbox resources will be more secure, switching process will consume a lot of resources, so using a single process experience is smoother

The Meaning of Multithreading (the Meaning of cashiers)

advantages

  1. Can improve the execution efficiency of the program
  2. Increase resource utilization (CPU, memory)
  3. When tasks on the thread are completed, the thread is automatically deregistered

disadvantages

  1. Starting threads takes up a certain amount of memory (512 KB per thread by default)
  2. If a large number of threads are enabled, a large amount of memory space will be occupied and the performance of the program will be reduced
  3. The more threads there are, the more overhead the CPU has on calling threads
  4. Programming is more complex, such as communication between threads, data sharing between multiple threads

Development:

Five memory partitions

Heap area, stack area, uninitialized constant area, initialized constant area, code area

Temporary variables are stored in the stack area

Principle of multithreading

The CPU quickly switches between threads in a unit time slice

Multithreaded life cycle

  • Create a new start -> Runnable ready -> Wait for CPU to schedule the current thread -> Run Running
  • Ready Runnable
  • Run Running/ wait for CPU to schedule the current thread
  • Blocked/Calls the sleep method, waits for a synchronization lock, and is removed from the schedulable thread pool
  • The death task is executed and forced to exit

# Thread pool principle

The thread pool size is smaller than the core thread pool size to determine whether the thread pool is full

  1. If saturation is not reached -> Create a thread to execute the task

  2. If saturation is reached -> The thread pool determines that the work queue is full

    1) Less than -> Push the task to queue

    2) full

    • A. If maximumPoolSize > corePoolSize, a new thread will be created to execute the task

    • B. Leave it to the saturation strategy

      A) Abort strategy: the default policy, a new task submitted directly throw unchecked exceptions RejectedExecutionException, the exception can be caught by the caller

      B)CallerRuns policy: does not discard tasks or throw exceptions, but pushes some tasks back to the caller for the moderation mechanism. Instead of executing a new task in a thread in the thread pool, the new task will run in the thread calling exector.

      C)Discard policy: The newly submitted task is discarded

      DiscardOldest: Enter a queue with the “head” task and then try to submit a new task.

Note: Start does not mean start running immediately

Code emulates the thread life cycle

Partial thread cycle method

  1. Create a thread

– (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument

  1. Thread start thread

– (void)start

  1. Cancel the thread

– (void)cancel

  1. Out of the thread

+ (void)exit;

  1. Set sleep Time

+ (void)sleepForTimeInterval:(NSTimeInterval)ti;

sleep(unsigned int)

  1. Is it being executed?

@property (readonly, getter=isExecuting) BOOL executing

  1. Is it finished?

@property (readonly, getter=isFinished) BOOL finished

  1. Has it been cancelled?

@property (readonly, getter=isCancelled) BOOL cancelled

Thread communication

Thread communication generally refers to the transmission of values between multiple threads

**NSPort: ** Some communication based on the end, end-to-end communication

Code to achieve thread communication function

PortViewController.m

#import "PortViewController.h"
#import <objc/runtime.h>
#import "KCPerson.h"

@interface PortViewController ()<NSMachPortDelegate>
@property (nonatomic, strong) NSPort *myPort;
@property (nonatomic, strong) KCPerson *person;

@end

@implementation PortViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"Port thread communication"; self.view.backgroundColor = [UIColor whiteColor]; Self. MyPort = [NSMachPort]; self. MyPort = [NSMachPort]; Self.myport.delegate = self; self.myport.delegate = self; [[NSRunLoop currentRunLoop] addPort:self.myPortforMode:NSDefaultRunLoopMode];
    
    self.person = [[KCPerson alloc] init];
    [NSThread detachNewThreadSelector:@selector(personLaunchThreadWithPort:)
                             toTarget:self.person
                           withObject:self.myPort];
    
}

#pragma mark - NSMachPortDelegate
- (void)handlePortMessage:(NSPortMessage *)message{
    NSLog(@"VC callback back == %@",[NSThread currentThread]);
}
Copy the code

KCPerson.h

@interface KCPerson : NSObject
- (void)personLaunchThreadWithPort:(NSPort *)port;
@end
Copy the code

KCPerson.m

#import "KCPerson.h"

@interface KCPerson()<NSMachPortDelegate>
@property (nonatomic, strong) NSPort *vcPort;
@property (nonatomic, strong) NSPort *myPort;
@end

@implementation KCPerson


- (void)personLaunchThreadWithPort:(NSPort *)port{
    
    NSLog(@"VC responds to Person"); Autoreleasepool {//1. Save the mainline port self.vcPort = port; //2. Set the name of the child thread [[NSThread currentThread]setName:@"KCPersonThread"]; Runloop [[NSRunLoop currentRunLoop] run]; // create self port self.myPort = [NSMachPort port]; Self.myport.delegate = self; self.myport.delegate = self; //6. Finish sending the message to the main thread port [self sendPortMessage]; }} /** * sendPortMessage {NSData *data1 = [@"ty"dataUsingEncoding:NSUTF8StringEncoding]; NSMutableArray *array =[[NSMutableArray alloc]initWithArray:@[data1,self.myPort]]; // Send a message to the main thread of the VC // first argument: send time. // msgid message id. // components, send messages with parameters. / / reserved: Number of bytes reserved for the header [self.vcPort sendBeforeDate:[NSDate Date] MSgid :10086 Components :array from: self.myport reserved:0]; }Copy the code

Print result:

The above code mainly completes such a process:

PortViewController -> KCPerson -> PortViewController

  1. The PortViewController calls the KCPerson instance method in the child thread and passes an NSPort
  2. KCPerson accepts the vcPort and stores it, creating a myPort of its own
  3. The KCPerson sends another message to the PortViewController using the vcPort, along with some parameters, such as myPort.
  4. The NSMachPortDelegate proxy in the PortViewController is called, and the message is the message passed from KCPerson.

This completes end-to-end communication between the main thread and child threads.

Then we see the NSMachPortDelegate method for NSPort

- (void)handlePortMessage:(NSPortMessage *)message{
    NSLog(@"VC callback back == %@",[NSThread currentThread]);
}
Copy the code

The callback takes an argument, NSPortMessage, to see what the arguments are

PortViewController.m

#pragma mark - NSMachPortDelegate

- (void)handlePortMessage:(NSPortMessage *)message{
    
    NSLog(@"VC callback back == %@",[NSThread currentThread]);
    [self getAllProperties:message];
}

- (void)getAllProperties:(id)somebody{
    
    u_int count = 0;
    objc_property_t *properties = class_copyPropertyList([somebody class], &count);
    for (int i = 0; i < count; i++) {
        const char *propertyName = property_getName(properties[i]);
         NSLog(@"% @",[NSString stringWithUTF8String:propertyName]); }}Copy the code

Print result:

Now that we know what the parameters are, let’s read and print the data that we sent back before

- (void)handlePortMessage:(NSPortMessage *)message{
    
    NSLog(@"VC callback back == %@",[NSThread currentThread]);
    
    NSLog(@"Pass some information from person :"); \ NSLog(@"receivePort == %@",[message valueForKey:@"receivePort"]);
    NSLog(@"sendPort == %@",[message valueForKey:@"sendPort"]);
    NSLog(@"msgid == %@",[message valueForKey:@"msgid"]);
    NSLog(@"components == %@",[message valueForKey:@"components"]);
Copy the code

Print result:

PortViewController communicates with KCPerson, and then KCPerson uses NSPort to send messages to PortViewController.

The PortViewController received a message from KCPerson, and now the PortViewController sends a message to KCPerson

Code implementation:

PortViewController.m

#import "PortViewController.h"
#import <objc/runtime.h>
#import "KCPerson.h"

@interface PortViewController ()<NSMachPortDelegate>
@property (nonatomic, strong) NSPort *myPort;
@property (nonatomic, strong) KCPerson *person;

@end

@implementation PortViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"Port thread communication";
    self.view.backgroundColor = [UIColor whiteColor];
    
    NSLog(@"PortViewController creates a child thread to call the KCPerson main thread method \n"); Self. MyPort = [NSMachPort]; self. MyPort = [NSMachPort]; Self.myport.delegate = self; self.myport.delegate = self; [[NSRunLoop currentRunLoop] addPort:self.myPortforMode:NSDefaultRunLoopMode];
    
    self.person = [[KCPerson alloc] init];
    [NSThread detachNewThreadSelector:@selector(personLaunchThreadWithPort:)
                             toTarget:self.person
                           withObject:self.myPort];
    
}


#pragma mark - NSMachPortDelegate

- (void)handlePortMessage:(NSPortMessage *)message{
    NSLog(@"After receiving a message from KCPerson, the PortViewController sends a message to KCPerson \n");
    
    NSData *data2 = [@"Janice"dataUsingEncoding:NSUTF8StringEncoding]; // This sendPort is the new port in KCPerson, so it needs to be added to NSRunLoop when sending messages. NSPort *sendPort = [message valueForKey:@"sendPort"];
    
    NSMutableArray *array = [[NSMutableArray alloc] initWithArray:@[data2, self.myPort]];
    
    [[NSRunLoop currentRunLoop] addPort:sendPort forMode:NSDefaultRunLoopMode]; // The main thread that sends the message KCPerson // the first argument: send time. // msgid message id. // components, send messages with parameters. / / reserved: Bytes reserved for the header BOOL rusElt = [sendPort sendBeforeDate:[NSDate Date] MSgid :10000 Components :array from:self.myPort reserved:0]; }Copy the code

KCPerson.h

#import <Foundation/Foundation.h>

@interface KCPerson : NSObject
- (void)personLaunchThreadWithPort:(NSPort *)port;
@end
Copy the code

KCPerson.m

#import "KCPerson.h"

@interface KCPerson()<NSMachPortDelegate>
@property (nonatomic, strong) NSPort *vcPort;
@property (nonatomic, strong) NSPort *myPort;
@end

@implementation KCPerson


- (void)personLaunchThreadWithPort:(NSPort *)port{
    
    NSLog(@"The method in KCPerson is called in the PortViewController via the child thread \n"); Autoreleasepool {//1. Save the mainline port self.vcPort = port; //2. Set the name of the child thread [[NSThread currentThread]setName:@"KCPersonThread"]; Runloop [[NSRunLoop currentRunLoop] run]; // create self port self.myPort = [NSMachPort port]; Self.myport.delegate = self; self.myport.delegate = self; //6. Finish sending the message to the main thread port [self sendPortMessage]; }} /** * Finish sending a port message to the main thread */ - (void)sendPortMessage {NSLog(@"KCPerson sends message \n to PortViewController");
 
    NSData *data1 = [@"ty" dataUsingEncoding:NSUTF8StringEncoding];
    NSData *data2 = [@"Janice"dataUsingEncoding:NSUTF8StringEncoding]; NSMutableArray *array =[[NSMutableArray alloc]initWithArray:@[data1,self.myPort]]; // Send a message to the main thread of the VC // first argument: send time. // msgid message id. // components, send messages with parameters. / / reserved: Number of bytes reserved for the header [self.vcPort sendBeforeDate:[NSDate Date] MSgid :10086 Components :array from: self.myport reserved:0]; }#pragma mark - NSMachPortDelegate

- (void)handlePortMessage:(NSPortMessage *)message{
    NSLog(@"KCPerson received some messages from the PortViewController :\n");
    NSLog(@"components == %@",[message valueForKey:@"components"]);
    NSLog(@"receivePort == %@",[message valueForKey:@"receivePort"]);
    NSLog(@"sendPort == %@",[message valueForKey:@"sendPort"]);
    NSLog(@"msgid == %@",[message valueForKey:@"msgid"]);
}

Copy the code

Print result:

You can compare the printed results to the code, so it’s easy to see

Extension: bridge between C and OC

  1. _bridge does only type conversions, but does not modify object (memory) management;
  2. _bridge_retained(CFBridgingRetain can also be used), which translates Objective-C objects into Core Foundation objects and allows us to manage the object (memory). You need to use CFRelease or related methods to release the object.
  3. _bridge_Transfer (also available using CFBridgingRelease) converts Core Foundation objects into Objective-C objects, while handing over object (memory) management to ARC.