美文网首页程序员
iOS 进程&线程&多线程

iOS 进程&线程&多线程

作者: iOS_July | 来源:发表于2018-07-06 15:16 被阅读63次
    2018年下半年学习.png

    写在前面吧:
    上图是下半年的学习计划进度脑图,默默坚持~~
    这篇文 只能算是一个观看笔记,感谢不死鸟大佬的教学,看完受益良多

    进程

    五态模型

    线程

    • 线程是进程的基本执行单元
    • 进程的所有任务都是在线程中执行


    多线程

    • 网络请求
    • 图片加载
    • 文件处理
    • 数据存储
    • 任务执行等

    串行
    串行耗时
    并行
    并行

    多线程实现原理

    单核
    多核

    多线程优缺点

    优点:
    • 简化了编程模型
    • 更加轻量级
    • 提高执行效率
    • 提高资源利用率
    缺点:
    • 增加了程序设计的复杂性
    • 占用内存空间
    • 增加了CPU的调度开销

    多线程实现技术方案

    pThread[基于C,移植性强]
    • 代码:
    ///pThread
    - (void)setupThreadWithpThread
    {
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        btn.frame = CGRectMake(100, 100, 100, 30);
        [btn setTitle:@"pThread" forState:UIControlStateNormal];
        [btn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
        [btn addTarget:self action:@selector(clickPThread) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:btn];
    }
    - (void)clickPThread
    {
        NSLog(@"我在主线程中执行");
        pthread_t pthread;
        pthread_create(&pthread, NULL, run, NULL);
    }
    void *run(void *data)
    {
        NSLog(@"我在子线程中执行");
        for (int i=1; i<10; i++) {
            NSLog(@"%d",i);
            sleep(1);
        }
        return NULL;
    }
    
    • 控制台:
    2018-07-05 16:12:14.838406+0800 TestThread[4503:324104] 我在主线程中执行
    2018-07-05 16:12:14.839701+0800 TestThread[4503:324183] 我在子线程中执行
    2018-07-05 16:12:14.841281+0800 TestThread[4503:324183] 1
    2018-07-05 16:12:15.844024+0800 TestThread[4503:324183] 2
    2018-07-05 16:12:16.845006+0800 TestThread[4503:324183] 3
    2018-07-05 16:12:17.845463+0800 TestThread[4503:324183] 4
    2018-07-05 16:12:18.848984+0800 TestThread[4503:324183] 5
    2018-07-05 16:12:19.853491+0800 TestThread[4503:324183] 6
    2018-07-05 16:12:20.857345+0800 TestThread[4503:324183] 7
    2018-07-05 16:12:21.859202+0800 TestThread[4503:324183] 8
    2018-07-05 16:12:22.860372+0800 TestThread[4503:324183] 9
    
    NSThread
    • 通过alloc init的方式创建并执行线程,可控制线程name属性
    NSThread *thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(runThread1) object:nil];
    [thread1 start];
    
    • 通过detachNewThreadSelector 方式创建并执行线程
    [NSThread detachNewThreadSelector:@selector(runThread1) toTarget:self withObject:nil];
    
    • 通过detachNewThreadSelector 方式创建并执行线程
    [NSThread detachNewThreadSelector:@selector(runThread1) toTarget:self withObject:nil];
    
    • 代码:
    - (void)setupThreadWithNSThread
    {
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        btn.frame = CGRectMake(100, 150, 100, 30);
        [btn setTitle:@"NSThread" forState:UIControlStateNormal];
        [btn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
        [btn addTarget:self action:@selector(clickNSThread) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:btn];
    }
    
    - (void)clickNSThread
    {
        NSLog(@"我在主线程中执行");
        [self performSelectorInBackground:@selector(runThread1) withObject:nil];
    }
    
    - (void)runThread1
    {
        NSLog(@"我在子线程中执行");
        for (int i=1; i<10; i++) {
            NSLog(@"%d",i);
            sleep(1);
            if (i == 9) {
                [self performSelectorOnMainThread:@selector(runMainThread) withObject:nil waitUntilDone:YES];
            }
        }
    }
    - (void)runMainThread
    {
        NSLog(@"回到线程中执行");
    }
    
    • 控制台:
    2018-07-05 16:34:08.496514+0800 TestThread[4718:338296] 我在主线程中执行
    2018-07-05 16:34:08.499321+0800 TestThread[4718:338376] 我在子线程中执行
    2018-07-05 16:34:08.500084+0800 TestThread[4718:338376] 1
    2018-07-05 16:34:09.575477+0800 TestThread[4718:338376] 2
    2018-07-05 16:34:10.576032+0800 TestThread[4718:338376] 3
    2018-07-05 16:34:11.648309+0800 TestThread[4718:338376] 4
    2018-07-05 16:34:12.721992+0800 TestThread[4718:338376] 5
    2018-07-05 16:34:13.794289+0800 TestThread[4718:338376] 6
    2018-07-05 16:34:14.869460+0800 TestThread[4718:338376] 7
    2018-07-05 16:34:15.944381+0800 TestThread[4718:338376] 8
    2018-07-05 16:34:17.018836+0800 TestThread[4718:338376] 9
    2018-07-05 16:34:18.094780+0800 TestThread[4718:338296] 回到线程中执行
    
    GCD

    注意的思考点:
    1->同步&异步
    2->串行&并行
    3->dispatch_get_main_queue() & dispatch_get_global_queue()
    4->dispatch_group_enter & dispatch_group_leave

    <-简单应用->

    • 代码:
    - (void)setupThreadWithGCD
    {
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        btn.frame = CGRectMake(100, 200, 100, 30);
        [btn setTitle:@"GCD" forState:UIControlStateNormal];
        [btn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
        [btn addTarget:self action:@selector(clickGCD) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:btn];
    }
    
    - (void)clickGCD
    {
        NSLog(@"执行GCD");
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
           //执行耗时任务
            NSLog(@"执行耗时任务 task1");
            [NSThread sleepForTimeInterval:3];
            
            dispatch_async(dispatch_get_main_queue(), ^{
                //回到主线程,刷新UI
                
                NSLog(@"回到主线程刷新UI");
            });
        });
    }
    
    • 控制台:
    2018-07-05 17:47:25.353341+0800 TestThread[5365:385948] 执行GCD
    2018-07-05 17:47:25.353779+0800 TestThread[5365:386006] 执行耗时任务 task1
    2018-07-05 17:47:28.359846+0800 TestThread[5365:385948] 回到主线程刷新UI
    

    <-按顺序执行->

    • 代码:
    /*
         * 执行--结束的顺序
         * DISPATCH_QUEUE_PRIORITY_LOW
         * DISPATCH_QUEUE_PRIORITY_HIGH
         * DISPATCH_QUEUE_PRIORITY_DEFAULT
    */
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
            NSLog(@"执行耗时任务 task1");
            [NSThread sleepForTimeInterval:2];
            NSLog(@"结束耗时任务 task1");
        });
        
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
            NSLog(@"执行耗时任务 task2");
            [NSThread sleepForTimeInterval:2];
            NSLog(@"结束耗时任务 task2");
        });
        
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            NSLog(@"执行耗时任务 task3");
            [NSThread sleepForTimeInterval:2];
            NSLog(@"结束耗时任务 task3");
        });
    
    • 控制台:
    2018-07-06 10:15:37.850583+0800 TestThread[951:33839] 执行GCD
    2018-07-06 10:15:37.850954+0800 TestThread[951:33906] 执行耗时任务 task2
    2018-07-06 10:15:37.850963+0800 TestThread[951:33905] 执行耗时任务 task3
    2018-07-06 10:15:37.850989+0800 TestThread[951:33908] 执行耗时任务 task1
    2018-07-06 10:15:39.853563+0800 TestThread[951:33906] 结束耗时任务 task2
    2018-07-06 10:15:39.853581+0800 TestThread[951:33905] 结束耗时任务 task3
    2018-07-06 10:15:39.895970+0800 TestThread[951:33908] 结束耗时任务 task1
    
    NSOperation[基类]``[线程池]``[最大并发数]

    使用的两种方式:
    1-->NSInvocationOperation
    2-->NSBlockOperation

    • 相关概念:

    1、NSOperationQueue:

    a. addOperation
    b. setMaxConcurrentOperationCount
    2、状态:
    readycancelledexecutingfinishedasynchronous
    3、依赖:
    addDependency

    • 代码:
    - (void)setupThreadWithNSOperation
    {
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        btn.frame = CGRectMake(100, 350, 150, 30);
        [btn setTitle:@"NSOperation" forState:UIControlStateNormal];
        [btn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];
        [btn addTarget:self action:@selector(clickNSOperation) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:btn];
    }
    
    - (void)clickNSOperation
    {
        NSLog(@"我是主线程");
        /*
        NSBlockOperation *blockOper = [NSBlockOperation blockOperationWithBlock:^{
            for (int i=0; i < 3; i++) {
                NSLog(@"invocation--%d",i);
                [NSThread sleepForTimeInterval:1];
            }
        }];
        [blockOper start];
        */
    
        /*
        NSInvocationOperation * invocationOper = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(invocationAction) object:nil];
        
        //start 方式启用,会是在当前程执行`[同步-非并发]`
        [invocationOper start];
        */
        
        //开启子线程,则会阻塞子线程
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            
            NSInvocationOperation * invocationOper = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(invocationAction) object:nil];
            
            [invocationOper start];
        });
    }
    - (void)invocationAction
    {
        for (int i=0; i < 3; i++) {
            NSLog(@"invocation--%d",i);
            [NSThread sleepForTimeInterval:1];
        }
    }
    
    • 控制台:
    2018-07-06 14:20:10.971880+0800 TestThread[2760:150878] 我是主线程
    2018-07-06 14:20:10.973186+0800 TestThread[2760:150932] invocation--0
    2018-07-06 14:20:11.977305+0800 TestThread[2760:150932] invocation--1
    2018-07-06 14:20:12.981491+0800 TestThread[2760:150932] invocation--2 
    

    结束语

    再次说明,这只是一篇笔记,要想真正用好多线程,短期内估计是不行,需要多练习了,共勉之~

    相关文章

      网友评论

        本文标题:iOS 进程&线程&多线程

        本文链接:https://www.haomeiwen.com/subject/giypuftx.html