iOS Development multithreading-technical Solutions

Source: Internet
Author: User
<span id="Label3"></p>Pthread Implementing multithreaded Operations<p><p>Code implementation:</p></p><pre><pre><code>void * run(void *param){    for (NSInteger i = 0; i < 1000; i++) {        NSLog(@"---buttonclick---%zd---%@", i, [NSThread currentThread]);    }    return NULL;}@implementation ViewController- (IBAction)clickButton:(id)sender {    // 定义一个线程    pthread_t thread;    // 创建一个线程  (参1)pthread_t *restrict:创建线程的指针,(参2)const pthread_attr_t *restrict:线程属性  (参3)void *(*)(void *):线程执行的函数的指针,(参4)void *restrict:null    pthread_create(&thread, NULL, run, NULL);    // 何时回收线程不需要你考虑    pthread_t thread2;    pthread_create(&thread2, NULL, run, NULL);}</code></pre></pre>Nsthread Implementing multithreading<p><p>A Nsthread object represents a thread</p></p>Multiple ways to create threads <ul class=" list-paddingleft-2"> <li><li><p>The first way: create a restart thread first</p><pre><code>  // 创建线程  NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"jack"];  // 线程启动了,事情做完了才会死, 一个NSThread对象就代表一条线程  [thread start];</code></pre></li></li> <li><li><p>Second type: Create and start a thread directly</p><pre><code>  // 直接创建并启动线程  [NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"jack"];</code></pre></li></li> <li><li><p>The third type:</p><pre><code>  // 直接创建并启动线程  [self performSelectorInBackground:@selector(run:) withObject:@"jack"];  // 使线程进入阻塞状态  [NSThread sleepForTimeInterval:2.0];  #pragma mark - 执行run方法  - (void)run:(NSString *)param  {      // 当前线程是否是主线程      for (NSInteger i = 0; i < 100; i++) {          NSLog(@"---%@---%zd---%d", [NSThread currentThread], i,  [NSThread isMainThread]);      }  }</code></pre></li></li> <li><li><p>Advantages of Method 2 and method 3: The advantages of shortcut method 1: you can easily get the thread</p></li></li> </ul>Inter-thread Communication <ul class=" list-paddingleft-2"> <ul class=" list-paddingleft-2"> <li><p>The embodiment of inter-thread communication</p></li> </ul> </ul><p><p>1 Threads pass data to another 1 threads</p></p><p><p>After performing a specific task in 1 threads, go to another 1 thread to continue the task</p></p><p><p>Common methods of Inter-thread communication: Small program image download</p></p><pre><pre><code>- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {    // 获取图片的url    NSURL *url = [NSURL URLWithString:@"http://7xjanq.com1.z0.glb.clouddn.com/6478.jpg"];// 另开1条线程 object用于数据的传递    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(downLoadWithURL:) object:url];    // 由于下面下载图片的耗时太长,应领开启线程来完成    [thread start];}// 下载图片- (void)downLoadWithURL:(NSURL *)url{    NSLog(@"%@", [NSThread currentThread]);    // 下载图片    NSData *data = [NSData dataWithContentsOfURL:url];    // 生成图片    UIImage *image = [UIImage imageWithData:data];    // 返回主线程显示图片    [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];}</code></pre></pre><p><p>The above two ways of using threads are obsolete, and most of our operating threads in development use GCD and nsoperation for multithreaded Operations.</p></p><p><p>The following I will give you a systematic introduction of how GCD is the implementation of multi-threaded</p></p>GCD Implementing Multithreading GCD Introduction<p><p>The GCD full name is Grand Central Dispatch, which translates to "super-powerful hub scheduler", GCD is a solution for multi-core parallel computing by apple, GCD automatically uses more CPU cores (such as dual-core, quad-core) to enable thread execution, GCD Automatically manages the life cycle of threads (creating threads, scheduling tasks, destroying Threads) without requiring our programmers to manually manage Memory.</p></p>Tasks and queues<p><p>Tasks: executing in synchronous functions and asynchronous functions</p></p><p><p>Queue: used to hold tasks (concurrent Serial)</p></p><p><p>The GCD automatically takes the task out of the queue and places it on the corresponding thread, and the Task's removal follows the fifo, which is the abbreviation for first-in, first-out queues, and Initial-Input-Output. The first entry task is completed and finished, followed by the next Task.</p></p>Synchronization functions and asynchronous functions, concurrent queues and serial queues <ul class=" list-paddingleft-2"> <ul class=" list-paddingleft-2"> <li><p>Perform tasks synchronously: tasks can be performed immediately in the current thread without the ability to open threads</p></li> <li><p>Perform a task asynchronously: perform a task at the end of the current thread, with the ability to open a new thread</p></li> <li><p>Concurrent queues: allow multiple tasks to execute concurrently</p></li> <li><p>Serial queue: Once a task is completed, the next task is executed</p></li> </ul> </ul><p><p>To create a concurrent/serial queue code:</p></p><pre><pre><code>// 创建并发队列 // 参1:const char *label 队列名称 // 参2:dispatch_queue_attr_t attr 队列类型dispatch_queue_t queueConcurrent = dispatch_queue_create("520it.com", DISPATCH_QUEUE_CONCURRENT);// 创建串行队列  serial 串行  concurrent并发dispatch_queue_t queueSerial = dispatch_queue_create("520it.com", DISPATCH_QUEUE_SERIAL);// 获取全局队列 全局队列是并发队列 // 参1:队列的优先级 // 参2:0(以后可能用到的参数)dispatch_queue_t queueGlobal = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);// 全局并发队列的优先级#define DISPATCH_QUEUE_PRIORITY_HIGH 2 // 高#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默认(中)#define DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后台// 获取主队列  在主队列中的任务都会在主线程中执行。dispatch_queue_t queueMain = dispatch_get_main_queue();</code></pre></pre><p><p>The Synchronous/asynchronous function code represents:</p></p><pre><code>GCD synchronous function Serial queue (immediate execution, current thread)//1:dispatch_queue_t queue//parameter 2: task Dispatch_sync (queueserial, ^{   for (nsinte Ger i = 0; I < 10; I++) {       nslog (@ "~~~%@", [nsthread currentthread]),  }});//synchronous function Parallel queue (immediate execution, current Thread) Dispatch_ Sync (queueconcurrent, ^{   for (nsinteger i = 0; i < i++) {       nslog (@ "~~~%@", [ Nsthread currentthread]);    });//asynchronous function Serial queue (another thread, multiple tasks executed sequentially) dispatch_async (queueserial, ^{   dispatch_async (queueserial, ^{       for (nsinteger i = 0; i < ten i++) {           nslog (@ "~ ~ ~ %@ ", [nsthread currentthread]);        }    });    dispatch_async (queueserial, ^{       for (nsinteger i = 0; i <; i++) {  &nbs P        nslog (@ "~~~%@", [nsthread currentthread]);        }    });    dispatch_async (queueserial, ^{       for (nsinteger i = 0; i < ten; i++) {           n SLog (@ "~~~%@", [nsthread currentthread]);        }    }); /async function Parallel Queue (another thread, multiple tasks executed together) dispatch_async (queueconcurrent, ^{   dispatch_async (queueserial, ^{           for (nsinteger i = 0; i < ten; i++) {                NSLog (@ "~~~%@", [nsthread currentthread]);            }    });    dispatch_async (queueserial, ^{       for (nsinteger i = 0; i <; i++) {  &nbs P        nslog (@ "~~~%@", [nsthread currentthread]);        }    });    dispatch_async (queueserial, ^{       for (nsinteger i = 0; i <; i++) {  &nbs P        nslog (@ "~~~%@", [nsthread currentthread]);       }    }); /home column: (any Task will be added to the main Thread's queue as long as it is in the primary Queue)</code></pre> <blockquote> <blockquote> <p>Note: Adding a task to the current serial queue with the sync function (sync Function) will get stuck in the current serial queue</p> </blockquote> </blockquote><p><p>Explanation: Use the synchronization function to add task A to the serial queue, stating that the code after task A will be executed immediately after task a finishes executing the current serial Queue. however, the current queue is a serial queue, which means that task a must wait until the task B in the current serial queue is completed before it can be executed, so you must perform the task immediately in task a, and you must wait until task B finishes executing to perform the next task, so it will Die. You wait for me, I wait for you, no one can Execute.</p></p>GCD Implementing thread Communication<p><p>Small item: Download picture</p></p><p><p>The code is as Follows:</p></p><pre><pre><code>// 获取图片的urlNSURL *url = [NSURL URLWithString:@"http://7xjanq.com1.z0.glb.clouddn.com/6478.jpg"];// 开启线程下载图片dispatch_queue_t queue = dispatch_queue_create("111", DISPATCH_QUEUE_CONCURRENT);dispatch_async(queue, ^{    NSData *data = [NSData dataWithContentsOfURL:url];    UIImage *image = [UIImage imageWithData:data];    // 下载完成后返回主线程显示图片    dispatch_async(dispatch_get_main_queue(), ^{        self.imageView.image = image;    });});</code></pre></pre>GCD Other common functions dispatch_barrier fence<pre><pre><code>// 1.barrier : 在barrier前面的先执行,然后再执行barrier,然后再执行barrier后面的 barrier的queue不能是全局的并发队列dispatch_queue_t queue = dispatch_queue_create("11", DISPATCH_QUEUE_CONCURRENT);dispatch_async(queue, ^{    for (int i = 0;  i < 100; i++) {        NSLog(@"%@--1", [NSThread currentThread]);    }});dispatch_async(queue, ^{    for (int i = 0;  i < 100; i++) {        NSLog(@"%@--2", [NSThread currentThread]);    }});dispatch_barrier_async(queue, ^{    for (int i = 0;  i < 100; i++) {        NSLog(@"%@--3", [NSThread currentThread]);    }});dispatch_async(queue, ^{    for (int i = 0;  i < 100; i++) {        NSLog(@"%@--4", [NSThread currentThread]);    }});</code></pre></pre><p><p>Dispatch_after deferred execution</p></p><pre><pre><code>// 延迟执行// 方法1[self performSelector:@selector(run:) withObject:@"参数" afterDelay:2.0];// 方法2dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{    for (NSInteger i = 0; i < 100; i++) {        NSLog(@"%@", [NSThread currentThread]);    }});// 方法3[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:NO];</code></pre></pre><p><p>Dispatch_once execution of the entire program in one run</p></p><pre><pre><code>// 整个程序中只执行一次static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{    // 一次性代码});</code></pre></pre><p><p>Function: implement a Single-grain object of a class</p></p><p><p>Singleton mode: share a single resource throughout the application (this resource only needs to be created initialized 1 times)</p></p><pre><pre><code>static id _person;+ (instancetype)sharePerson{    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        _person = [[super alloc] init];    });    return _person;}+ (instancetype)allocWithZone:(struct _NSZone *)zone{    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        _person = [super allocWithZone:zone];    });    return _person;}- (id)copy{    return _person;}</code></pre></pre><p><p>In the development of general custom macro, more convenient, a line of code to FIX.</p></p>Dispatch_apply Fast Iteration<p><p>Sample Applet: cut a picture in one folder to another folder</p></p><pre><pre><code>// 将图片剪切到另一个文件夹里NSString *from = @"/Users/Ammar/Pictures/壁纸";NSString *to = @"/Users/Ammar/Pictures/to";NSFileManager *manager = [NSFileManager defaultManager];NSArray *subPaths = [manager subpathsAtPath:from];// 快速迭代dispatch_apply(subPaths.count, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index) {   NSLog(@"%@ - %zd", [NSThread currentThread], index);    NSString *subPath = subPaths[index];    NSString *fromPath = [from stringByAppendingPathComponent:subPath];    NSString *toPath = [to stringByAppendingPathComponent:subPath];    // 剪切    [manager moveItemAtPath:fromPath toPath:toPath error:nil];    NSLog(@"%@---%zd", [NSThread currentThread], index);});</code></pre></pre><p><p>Dispatch_group Queue Group</p></p><p><p>Sample Applet: requirements Download image 1 Download Picture 2 Add a new picture to picture 1 and picture 2</p></p><p><p>//create Queue <br>    dispatch_queue_t queue = Dispatch_get_global_queue (dispatch_queue_priority_default, 0); </p> </p><pre><code>Create groups dispatch_group_t group = dispatch_group_create ();//use Group queue to download pictures 1dispatch_group_async (group, queue, ^{    NSData *data = [nsdata datawithcontentsofurl:[nsurl urlwithstring:@ "http://7xjanq.com1.z0.glb.clouddn.com/6478.jpg" ]];    self.image1 = [UIImage imagewithdata:data];    nslog (@ "1%@", [nsthread currentthread]); /use group queue to download pictures 2dispatch_group_async (group, queue, ^{   nsdata *data = [nsdata Datawithcontentsofurl:[nsurl urlwithstring:@ "http://7xjanq.com1.z0.glb.clouddn.com/6478.jpg"];    self.image2 = [UIImage imagewithdata:data];    nslog (@ "2%@", [nsthread currentthread]); /add picture 1 and Picture 2 to a picture dispatch_group_notify (group, queue, ^{   cgfloat Imagew = self.imageView.bounds.size.width;    cgfloat Imageh = self.imageView.bounds.size.height;    //open Bitmap context    uigraphicsbeginimagecontext (self.imageView.bounds.size);    //drawing    [self.image1 drawinrect:cgrectmake (0, 0, imaGeW * 0.5, imageh)];    [self.image2 drawinrect:cgrectmake (imagew * 0.5, 0, Imagew * 0.5, imageh)];    //the picture out    uiimage *image = Uigraphicsgetimagefromcurrentimagecontext ();    //close The graphics context    uigraphicsendimagecontext ();    //display pictures on the main thread    dispatch_async (dispatch_get_main_queue (), ^{        Self.imageView.image = image;    });    nslog (@ "3%@", [nsthread currentthread]);});</code></pre>GCD Timer<p><p>GCD timers are not affected by mode and are therefore more accurate than nstimer</p></p><pre><code>static int count = 0;dispatch_after (dispatch_time (dispatch_time_now, (int64_t) (2.0 * nsec_per_sec)), dispatch_get_main _queue (), ^{   //the Meaning of this sentence is now very understood});//gcd timer dispatch_queue_t queue = Dispatch_get_global_queue (dispatch_queue _priority_default, 0);//1. Create a timer source//parameter 1: type timer//parameter 2: handle//parameter 3:mask 0//parameter 4: queue   (note: dispatch_source_t essence is oc object, representing Source) Self.timer = dispatch_source_create (dispatch_source_type_timer, 0, 0, queue);//rigorous, time interval needs to use unit int64_t, do multiplication after the unit changed// The following code indicates how much the callback function interval is int64_t interval = (int64_t) (2.0 * nsec_per_sec); How to set the start time CGD gave us a way to set the time  //1:dispatch_time_t when to pass a time, delta is the increment dispatch_time_t start = Dispatch_time ( dispatch_time_now, (int64_t) (3.0 * nsec_per_sec)); Starting from now 3 seconds//2. set the various properties of the Timer//parameter 1:timer//parameter 2: start time//parameter 3: time Interval//parameter 4: Pass 0 does not need   Dispatch_time_now indicates that GCD time is now expressed in NS Dispa Tch_source_set_timer (self.timer, start, interval, 0);//3. Set the callback (that is, what to do at each Interval) Dispatch_source_set_event_handler ( self.timer, ^{   nslog (@ "----------------%@", [nsthreadcurrentthread]);    //if you want to do it 5 times, stop    count++;    if (count = = 5) {       dispatch_cancel (self.timer),        self.tim ER = nil;    });//4. Start timer   (restore) Dispatch_resume (self.timer);</code></pre><p><p>Finish speaking GCD should talk about nsoperation, it is GCD object-oriented package, It is more convenient to use,</p></p>Nsoperation Implementing multithreading<p><p>Nsoperation is an abstract class and does not have the ability to encapsulate operations, it must use its subclasses</p></p><pre><pre><code>NSInvocationOperationNSBlockOperation自定义子类继承NSOperation,实现内部相应的方法</code></pre></pre><p><p>To implement multithreaded steps with Nsoperation:</p></p><pre><pre><code>创建任务 NSOperation 对象创建 NSOperationQueue 队列将任务 NSOperation 对象 add 到 NSOperationQueue 队列中去</code></pre></pre><p><p>Nsinvocationoperation</p></p><p><p>The code is as Follows:</p></p><pre><pre><code>NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];[op start];</code></pre></pre><p><p>Note: by default, Calling the Start method does not open a new thread to execute, but instead executes the operation synchronously in the current thread, and the operation is performed asynchronously only if the nsoperation is placed in a nsoperationqueue</p></p>Nsblockoperation<pre><pre><code>NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{    // 在主线程      NSLog(@"下载1------%@", [NSThread currentThread]);}];// 添加额外的任务(在子线程执行),封装数大于1才会异步执行[op addExecutionBlock:^{    NSLog(@"下载2------%@", [NSThread currentThread]);}];</code></pre></pre><p><p>Custom operation: need to implement-(void) the main method, what needs to be done in the Mian method</p></p>Nsoperationqueue<p><p>Create a queue using Nsoperationqueue: primary and global queues</p></p><pre><pre><code>// 创建一个其他队列(包括串行队列和并发队列) 放到这个队列中的NSOperation对象会自动放到子线程中执行NSOperationQueue *queue = [[NSOperationQueue alloc] init];// 创建一个主队列,放到这个队列中的NSOperation对象会自动放到子线程中执行NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];// 表示并发数量:即同时执行任务的最大数。queue.maxConcurrentOperationCount = 1;</code></pre></pre>cancellation, pause, and recovery of a queue:<pre><pre><code>// NSOpertion的 - cancel 方法也可以停止单个操作- (void)cancelAllOperations; // YES代表暂停队列,NO代表恢复队列- (void)setSuspended:(BOOL)b;</code></pre></pre>Add dependency<pre><pre><code>NSOperationQueue *queue = [[NSOperationQueue alloc] init];NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{    NSLog(@"download1 -------------- %@", [NSThread currentThread]);}];NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{    NSLog(@"download2 -------------- %@", [NSThread currentThread]);}];NSBlockOperation *block3 = [NSBlockOperation blockOperationWithBlock:^{    NSLog(@"download3 -------------- %@", [NSThread currentThread]);}];// 添加依赖: block1 和 block2执行完后 再执行 block3  block3依赖于block1和block2// 给block3添加依赖 让block3在block1和block2之后执行[block3 addDependency:block1];[block3 addDependency:block2];[queue addOperation:block1];[queue addOperation:block2];[queue addOperation:block3];</code></pre></pre><p><p>Note: you cannot loop dependencies, but you can cross-queue dependencies regardless of which queue the Nsoperation object is IN. As long as two nsoperation objects can be relied upon</p></p>Inter-thread Communication<p><p>example: Download a picture</p></p><pre><pre><code>// 下载图片 operation实现线程间通信[[[NSOperationQueue alloc] init] addOperation:[NSBlockOperation blockOperationWithBlock:^{    UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://7xjanq.com1.z0.glb.clouddn.com/6478.jpg"]]];    // 返回主线程    [[NSOperationQueue mainQueue] addOperation:[NSBlockOperation blockOperationWithBlock:^{        self.imageView.image = image;    }]];}]];</code></pre></pre><p><p>example: download picture 1 and Picture 2 and synthesize the picture</p></p><pre><code>Nsoperationqueue *queue = [[nsoperationqueue alloc] init];//download picture 1__block UIImage *image1 = nil; Nsblockoperation *block1 = [nsblockoperation blockoperationwithblock:^{   image1 = [UIImage imageWithData:[ NSData Datawithcontentsofurl:[nsurl urlwithstring:@ "http://7xjanq.com1.z0.glb.clouddn.com/6478.jpg"]]];}];/ /download image 2__block UIImage *image2 = nil; Nsblockoperation *block2 = [nsblockoperation blockoperationwithblock:^{   image2 = [UIImage imageWithData:[ NSData Datawithcontentsofurl:[nsurl urlwithstring:@ "http://7xjanq.com1.z0.glb.clouddn.com/6478.jpg"] [];}]; CGFloat Imagew = self.imageView.bounds.size.width; CGFloat Imageh = self.imageview.bounds.size.height;//synthetic picture Nsblockoperation *block3 = [nsblockoperation blockoperationwithblock:^{   uigraphicsbeginimagecontext (cgsizemake (imagew, imageH));    [ Image1 drawinrect:cgrectmake (0, 0, imagew * 0.5, imageh)];    [image2 drawinrect:cgrectmake (0.5 * imagew, 0, 0.5 * imagew, imageh)];   &NBSP UIImage *image3 = Uigraphicsgetimagefromcurrentimagecontext ();    uigraphicsendimagecontext ();    //switch back to the main thread display picture    [[nsoperationqueue mainqueue] addoperation:[nsblockoperation blockoperationwithblock:^{       self.imageview.image = image3;    }]];}];/ /set Dependency [block3 adddependency:block1]; [block3 adddependency:block2];//add task to queue [addoperation:block1]; [queue addoperation:block2]; [queue addoperation:block3];</code></pre>Application<p><p>Application: Sdwebimage framework of the underlying main function implementation is based on multi-threading, using multi-threading, we can achieve a small picture of the multi-image Download. The logic here is actually quite complicated.</p></p><p><p>To achieve a small picture of multi-image download ideas:</p></p><p><p></p></p><p><p>The code implementation is shown in the Code.</p></p><p><p>See this code: multithreading</p></p><pre><pre><code>https://github.com/lizhaoLoveIT/Multithreading</code></pre></pre><p><p>iOS Development multithreading-technical Solutions</p></p></span>

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.