iOS 多线程笔记

iOS 多线程笔记_第1张图片

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

进程

iOS 多线程笔记_第2张图片


线程

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


多线程

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

串行

iOS 多线程笔记_第3张图片

并行

iOS 多线程笔记_第4张图片

多线程实现原理

iOS 多线程笔记_第5张图片
iOS 多线程笔记_第6张图片

多线程优缺点

优点:
  • 简化了编程模型
  • 更加轻量级
  • 提高执行效率
  • 提高资源利用率
缺点:
  • 增加了程序设计的复杂性
  • 占用内存空间
  • 增加了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开发笔记)