zoukankan      html  css  js  c++  java
  • iOS中多线程的实现方案

    什么是主线程?

    一个iOS程序运行后,默认会开启一条线程,称为“主线程”或“UI线程”

    主线程的主要作用

    1.显示/刷新UI界面

    2.处理UI事件(比如点击事件,滚动事件,拖拽事件)

    主线程的使用注意

    1.别将比较耗时的操作放在主线程中

    2.耗时操作会卡在主线程中,严重影响UI的流畅程度

    如图,将耗时操作放在主线程中,任务会按照串行顺序执行,在第五秒点击按钮之后,界面会卡住5秒

    因为耗时操作还没有执行完,不能立即响应按钮的点击

    1.pthread的使用

    void *run(void *parme) {
        
        NSLog(@"%@",[NSThread currentThread]);
        
        
        for (int i = 0; i < 100000; i++) {
            NSLog(@"%d",i);
        }
        return NULL;
        
    }
    
    - (IBAction)btnClick:(id)sender {
        
        pthread_t thread;
        pthread_create(&thread, NULL, run, NULL);
        
    }

    2.NSThread的使用

    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        [self createThread3];
    }
    
    //第一种创建方法
    - (void)createThread1 {
        //需要几个线程就alloc几个
        NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"第一种"];
        thread.name = @"one_thread";
        [thread start];
    }
    //第二种创建方法
    - (void)createThread2 {
        
        [NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"第二种"];
    }
    
    //第三种创建方法
    - (void)createThread3 {
        
        [self performSelectorInBackground:@selector(run:) withObject:@"第三种"];
    }
    
    - (void)run:(NSString *)param {
        NSLog(@"______%@_____%@",param,[NSThread currentThread]);
    }

    3.GCD的使用

    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        [self syncMain];
    }
    
    /**
     同步函数+主队列
     */
    - (void)syncMain {
        dispatch_queue_t queue = dispatch_get_main_queue();
        
        NSLog(@"syncMain ---- begin");
        //将任务加入到队列
        dispatch_sync(queue, ^{
            NSLog(@"1----%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"2----%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"3----%@",[NSThread currentThread]);
        });
        
        NSLog(@"syncMain ---- end");
    }
    
    /**
     异步函数+主队列
     */
    - (void)asyncMain {
        
        //异步函数用在主队列上就不会开线程了
        //获得串行队列
        dispatch_queue_t queue = dispatch_get_main_queue();
        
        //将任务加入到队列
        dispatch_async(queue, ^{
            NSLog(@"1----%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"2----%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"3----%@",[NSThread currentThread]);
        });
    }
    
    /**
     同步函数+串行队列:不会开启新的线程,在当前线程执行任务
     */
    - (void)syncSerial {
        //创建串行队列
        dispatch_queue_t queue = dispatch_queue_create("com.520.queue", DISPATCH_QUEUE_SERIAL);
        
        //将任务加入到队列
        dispatch_sync(queue, ^{
            NSLog(@"1----%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"2----%@",[NSThread currentThread]);
        });
        dispatch_sync(queue, ^{
            NSLog(@"3----%@",[NSThread currentThread]);
        });
    }
    
    /**
     异步函数+串行队列:会开启新的线程,但是任务是串行的,执行完一个任务,再执行下一个任务
     */
    - (void)asyncSerial {
        //创建串行队列
        dispatch_queue_t queue = dispatch_queue_create("com.520.queue", DISPATCH_QUEUE_SERIAL);
        
        //将任务加入到队列
        dispatch_async(queue, ^{
            NSLog(@"1----%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"2----%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"3----%@",[NSThread currentThread]);
        });
    }
    
    /**
     同步函数+并发队列:不会开启线程,不能
     */
    - (void)syncConcurrent {
        //获得全局的并发队列
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        
        //将任务添加到队列
        dispatch_async(queue, ^{
            NSLog(@"1----%@",[NSThread currentThread]);
        });
    
        dispatch_async(queue, ^{
            NSLog(@"1----%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            NSLog(@"1----%@",[NSThread currentThread]);
        });
    }
    
    /**
     异步函数+并发队列:可以同时开启多条线程
     */
    - (void)asycConcurrent {
        //创建一个队列
        //第一个参数是标签等同于名字
        //第二个参数传串行还是并行
    //    dispatch_queue_t queue = dispatch_queue_create("img.download", DISPATCH_QUEUE_CONCURRENT);
    
        //获得全局的并发队列
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        
        //将任务添加到队列
        dispatch_async(queue, ^{
            for (int i = 0; i < 10; i++) {
                NSLog(@"1----%@",[NSThread currentThread]);
            }
        });
        
        //将任务添加到队列
        dispatch_async(queue, ^{
            for (int i = 0; i < 10; i++) {
                NSLog(@"2----%@",[NSThread currentThread]);
            }
        });
        
        //将任务添加到队列
        dispatch_async(queue, ^{
            for (int i = 0; i < 10; i++) {
                NSLog(@"3----%@",[NSThread currentThread]);
            }
        });
    }
    View Code

    在使用GCD时,主要分为两步

    1.定制任务

    2.将任务添加到队列

    这里还需要区分下同步,异步,并行,串行

    同步异步:影响是否开启新的线程

    并行串行:影响任务的执行方式

    4.NSOperation的使用

    NSOperation是抽象类,并不具备封装操作,必须使用它的子类

    使用NSOperation子类的方式有三种

    1.NSInvocationOperation

    2.NSBlockOperation

    3.自定义子类继承NSOperation,实现内部响应的方法

    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        
        //创建队列
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        
        //创建任务1(invocationOperation方法)
        NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download1) object:nil];
     
        
        //创建任务2(blockOperation方法)
        NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"download2----%@",[NSThread currentThread]);
        }];
        
        [op2 addExecutionBlock:^{
            NSLog(@"download3----%@",[NSThread currentThread]);
        }];
        
        
        //创建任务3(自定义方法)
        DDZOperation *op3 = [[DDZOperation alloc] init];
        
        //添加任务到队列中
        [queue addOperation:op1];//内部自动调start方法
        [queue addOperation:op2];
        [queue addOperation:op3];
    }
    
    - (void)download1 {
        NSLog(@"download1----%@",[NSThread currentThread]);
    }
    View Code

    补充在自定义的DDZOperation中只有实现main方法才会开启线程处理任务

    @implementation DDZOperation
    
    - (void)main {
        NSLog(@"自定义-----%@",[NSThread currentThread]);
    }
  • 相关阅读:
    phpcms后台进入地址(包含No permission resources错误)
    phpmyadmin上传大sql文件办法
    ubuntu彻底卸载mysql
    Hdoj 2602.Bone Collector 题解
    一篇看懂词向量
    Hdoj 1905.Pseudoprime numbers 题解
    The Python Challenge 谜题全解(持续更新)
    Hdoj 2289.Cup 题解
    Hdoj 2899.Strange fuction 题解
    Hdoj 2199.Can you solve this equation? 题解
  • 原文地址:https://www.cnblogs.com/langji/p/5319427.html
Copyright © 2011-2022 走看看