Preface:

No matter Android or IOS, multi-task is used. The smallest unit of multi-task is thread. Today, WE will summarize the use of NSThread in IOS.

NSThread used?

The first way is instantiation

//selector: a method executed by a thread that takes only one argument and returns no value. / / target: Argument: the only argument passed to target, NSThread *newThread = [[NSThread alloc]initWithTarget:self selector:@selector(threadRun) object:nil];Copy the code

Two other initialization functions can also be used

NSThread  *newThread=[[NSThread alloc]init];
NSThread  *newThread= [[NSThread alloc]initWithBlock:^{
        NSLog(@"initWithBlock");
    }];Copy the code

Some properties commonly used by threads

// Set the thread name [newThread setName:@" thread-1 "]; // setThreadPriority [newThread setThreadPriority:1.0]; / / IOS after eight It is recommended to use this method sets the thread priority / / NSQualityOfServiceUserInteractive: the highest priority, for user interaction events / / NSQualityOfServiceUserInitiated: Higher priority to the user needs to immediately execute event / / NSQualityOfServiceDefault: the default priority, the main thread and not set priority thread is the default for this priority / / NSQualityOfServiceUtility: Ordinary priority for common tasks / / NSQualityOfServiceBackground: the lowest priority, for not important task [newThread setQualityOfService: NSQualityOfServiceUtility]; // check whether the thread is the main thread [newThread isMainThread]; // Whether the thread status has been cancelled [newThread isCancelled]; [newThread isFinished]; // Whether you are executing [newThread isExecuting];Copy the code

Threads start, cancel, and pause

// thread start [newThread start]; // Thread cancels [newThread cancel]; // Thread pause [NSThread sleepForTimeInterval:1.0]; / / or below this way let the thread to sleep 1 second [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 1.0]]. // Immediately terminate all threads except the main thread [NSThread exit];Copy the code

The second way is the method class

//selector: a method executed by a thread that takes only one argument and returns no value. / / target: Argument: the only argument passed to target, Can also be nil [NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:@" LCJ "];Copy the code

The thread is automatically started after it is created

Get current thread

[NSThread currentThread];Copy the code

Get main thread

 [NSThread mainThread];Copy the code

The third way is implicit creation

Used for communication between threads, such as specifying that tasks are executed in the current thread

// No argument is passed to specify that the function executes [self performSelector:@selector(doSomething)] on the current thread; // Pass the argument to specify that the function executes on the current thread [self performSelector: @selector(doSomething: withObject:tempStr]; [self performSelector:@selector(doSomething: withObject:tempStr afterDelay:2.0]];Copy the code

Specifies execution on a specific thread

/ / specified in the main thread in other threads execute [self performSelectorOnMainThread: @ the selector (doSomething:) withObject: tempStr waitUntilDone: YES]; / / specified in the main thread in the background thread execution [self performSelectorInBackground: @ the selector (doSomething:) withObject: tempStr); // Specify a particular thread in the main thread to perform [self performSelector:@selector(doSomething:) onThread:newThread withObject:tempStr waitUntilDone:YES];Copy the code

Thread synchronization

Thread synchronization is to solve the problem of data disorder caused by multiple threads accessing public shared data at the same time, and then use synchronization to make public data can only be accessed by one thread at the same time to avoid data disorder.

Let’s take a look at the problem of multithreaded access data being corrupted when unsynchronized. First, declare three threads

    NSThread *thread1=[[NSThread alloc]initWithTarget:self selector:@selector(taskRun) object:nil];
    thread1.name=@"thread-1";
    
    NSThread *thread2=[[NSThread alloc]initWithTarget:self selector:@selector(taskRun) object:nil];
    thread2.name=@"thread-2";
    
    NSThread *thread3=[[NSThread alloc]initWithTarget:self selector:@selector(taskRun) object:nil];
    thread3.name=@"thread-3";
    
    [thread1 start];
    [thread2 start];
    [thread3 start];Copy the code

The taskRun function operates on all variables count

-(void)taskRun {while (count>0) {NSThread sleepForTimeInterval:0.1]; count--; NSLog(@"threadName:%@ count:%d ",[NSThread currentThread].name, count); }}Copy the code

Running results:

Through the above data, you will find that there is an obvious confusion problem, resulting in data out of sync.

There are several ways to implement thread synchronization:

The first way @synchronized keyword

-(void)taskRun {while (count>0) {@synchronized(self) {NSThread sleepForTimeInterval:0.1]; count--; NSLog(@"threadName:%@ count:%d ",[NSThread currentThread].name, count); }}}Copy the code

The execution result

The second method is NSLock

Start by creating an NSLock synchronization lock object

threadLock=[[NSLock alloc]init];Copy the code

It then calls lock at the beginning of the block and unLock at the end

-(void)taskRun { while (count>0) { [threadLock lock]; [NSThread sleepForTimeInterval: 0.1]; count--; NSLog(@"threadName:%@ count:%d ",[NSThread currentThread].name, count); } [threadLock unlock]; }Copy the code

The third way uses the NSCondition synchronized lock and thread inspector

The main purpose of locking is to protect data sources when detecting conditions and perform tasks triggered by conditions; The thread checker mainly decides whether to continue running a thread based on conditions, that is, whether the thread is blocked. I’m going to create an NSCondition object

condition=[[NSCondition alloc]init];Copy the code

Synchronous locks are used in a similar way to NSLocks

-(void)taskRun
{
    
    while (count>0) {
        [condition lock];
        [NSThread sleepForTimeInterval:0.1];
        count--;
        NSLog(@"threadName:%@ count:%d ",[NSThread currentThread].name, count);
        [condition unlock];
    }
    
}Copy the code


NSCondition can tell a thread to wait and then get a signal from the CPU telling the thread to stop waiting and to continue, so let's change the example a little bit and let's make thread three just send the signal sourceCopy the code
 NSThread *thread1=[[NSThread alloc]initWithTarget:self selector:@selector(taskRun) object:nil];
    thread1.name=@"thread-1";
    
    NSThread *thread2=[[NSThread alloc]initWithTarget:self selector:@selector(taskRun) object:nil];
    thread2.name=@"thread-2";
    
    NSThread *thread3=[[NSThread alloc]initWithTarget:self selector:@selector(taskRun1) object:nil];
    thread3.name=@"thread-3";
    
    [thread1 start];
    [thread2 start];
    [thread3 start];Copy the code

The taskRun1 function is used to send signal sources

-(void)taskRun1 { while (YES) { [condition lock]; [NSThread sleepForTimeInterval:2]; [condition signal]; [condition unlock]; }}Copy the code

The taskRun function is used to perform the operation on count

-(void)taskRun
{
    
    while (count>0) {
        [condition lock];
        [condition wait];
        [NSThread sleepForTimeInterval:0.1];
        count--;
        NSLog(@"threadName:%@ count:%d ",[NSThread currentThread].name, count);
        [condition unlock];
    }
    
}Copy the code

Count — is executed only when Thread-1 and Thread-2 receive the signal source. Otherwise, thread-1 and Thread-2 are in wait state.

Conclusion:

I simply learned the use of IOS NSThread and had a preliminary understanding of IOS threads.