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]);

            }

        });

    }

     

    在使用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]);

    }

     

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

     

    @implementation DDZOperation

     

    - (void)main {

        NSLog(@"自定义-----%@",[NSThread currentThread]);

    }

  • 相关阅读:
    使企点QQ来消息时不自动弹出窗口(以避免错过旧的消息和避免正在回复A时自动定位到B从而影响客服效率)
    8款开源聊天软件
    博客园设置皮肤(宽屏等)及选择文本编辑器
    Windows Server 2019 设置使用照片查看器查看图片
    使windows10重启后打开上次的文件夹和程序
    TinyMCE 5 富文本编辑器好
    wordpress 安装 Elementor PRO 插件(破解版)
    无法打印,提示“windows 打印后台处理程序 没有运行”的解决方案
    第一次将代码提交至git error: failed to push some refs to 'https://gitee.com/xxx/test.git'
    git本地和远程的关联问题
  • 原文地址:https://www.cnblogs.com/fengmin/p/5453845.html
Copyright © 2011-2022 走看看