UI高级------多线程(线程与进程)

一.线程与进程

进程与线程的理解:
- CPU(工厂)—进程(车间)—-线程(工人):如下图
这里写图片描述

进程与线程的资源共享:

  • 车间的空间是工人们共享的,比如许多房间是每个工人都可以进出的。这象征 一个进程的内存空间是共享的,每个线程都可以使用这些共享内存.

    加锁机制(控制资源管理):

  • 可是,每间房间的大小不同,有些房间最多只能容纳一个人,比如厕所。里面 有人的时候,其他人就不能进去了。这代表一个线程使用某些共享内存时,其他线 程必须等它结束,才能使用这一块内存
  • 一个防止他人进入的简单方法,就是门口加一把锁。先到的人锁上门,后到的人 看到上锁,就在门口排队,等锁打开再进去。这就叫“互斥锁”(Mutual exclusion, 缩写 Mutex),防止多个线程同时读写某一块内存区域.
    信号量:
  • 还有些房间,可以同时容纳n个人,比如厨房。也就是说,如果人数大于n,多出 来的人只能在外面等着。这好比某些内存区域,只能供给固定数目的线程使用.
  • 这时的解决方法,就是在门口挂n把钥匙。进去的人就取一把钥匙,出来时再把钥 匙挂回原处。后到的人发现钥匙架空了,就知道必须在门口排队等着了。这种做法叫 做”信号量”(Semaphore),用来保证多个线程不会互相冲突。
  • 不难看出,mutex是semaphore的一种特殊情况(n=1时)。也就是说,完全可 以用后者替代前者。但是,因为mutex较为简单,且效率高,所以在必须保证资源独 占的情况下,还是采用这种设计。

    操作系统的设计,因此可以归结为三点:

  • (1)以多进程形式,允许多个任务同时运行;
  • (2)以多线程形式,允许单个任务分成不同的部分运行;
  • (3)提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之 间和线程之间共享资源

    进程与线程的区别:

  • 进程是指在系统中正在运行的一个应用程序,都有独立的内存空间,一般来说一个应 用程序存在一个进程,但也多个进程的情况
  • 同一个进程中的线程共享内存和资源

二.线程生命周期

CPU的使用权:

线程(thread)
- 程序执行的最小单元,按照线性顺序执行的一个流程,CPU的调度单位,一核同时只
能执行一个线程

多线程

  • 一个应用程序有多个线程,多线程不是为了提高运行效率,而是为了提高资源使用效 率来提高系统的效率
  • 一个程序有且只有一个主线程,程序启动时创建(调用main来启动)主线程的生命周 期是和应用程序绑定的,程序退出(结束)时,主线程也就停止了
  • 任何有可能堵塞主线程的任务不要在主线程执行(比如访问网络)

    单线程与多线程的执行图:
    这里写图片描述

    线程的生命周期:
    这里写图片描述

  • 新建状态(New):新创建了 一个线程对象
  • 就绪状态(Runnable):线 程对象创建后,其他线程调用 了该对象的start()方法,该状 态的线程位于可运行线程池中, 变得可运行,等待获取CPU 的使用权

  • 运行状态(Running):就绪状态的线程获取了CPU ,执行程序代码

  • 阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行 ,直到线程进入就绪状态,才有机会转到运行状态

  • 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期

三.线程调度

线程的使用:
线程实现

  • NSTread
    优点:NSTread比其他两个轻量级
    缺点:需要自己管理线程的生命周期,线程同步,加锁等
  • Cocoa operation
    优点:不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上
    Cocoa operation相关的类是NSOpration,NSOperationQuque.
    NSOperationQuque是操作队列,用来管理和控制NSOpration.NSOpration是操作任务,是抽象类,使用它必须用它的类.
  • GCD(Grand Central Dispatch)
    • GCD是一个替代诸如NSThread, NSOperationQueue, NSInvocationOperation等技术的
      一个高效、强大、底层的技术。

线程的使用,代码实现:
NSThread的创建

#import "ViewController.h"
#import "CustomThread.h"

@interface ViewController ()

@end

@implementation ViewController

/*
 1 NSThread 常用的类 属性 方法
 2 case1~case4
 3 退出 取消
 */

- (void)viewDidLoad {
    [super viewDidLoad];

    //case1
    NSThread *thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(threadCallMethod) object:nil];

    //启动线程,调用start方法
    [thread1 start];

    //线程的退出 (只是退出后面还没有来得及执行的线程)
//    [NSThread exit];


    //指定线程退出
    //(1)先标记thread1的状态是cancel
    [self performSelector:@selector(cancelThread1:) withObject:thread1 afterDelay:1];


    //case2 (没有返回值 不需要调用start方法)
//    [NSThread detachNewThreadSelector:@selector(threadCallMethod) toTarget:self withObject:nil];

    //case3
//    [self performSelectorInBackground:@selector(threadCallMethod) withObject:nil];

//    [self performSelectorOnMainThread:<#(nonnull SEL)#> withObject:<#(nullable id)#> waitUntilDone:<#(BOOL)#>]

    //case4 自定义线程
//    CustomThread *thread4 = [[CustomThread alloc]init];

    //启动方法
    //直接调用main方法,只是调用了一个普通的方法
//    [thread4 main];

    //启动线程 新的线程会执行相应线程汇总的main方法,并且会开辟一个新的线程
//    [thread4 start];

    NSLog(@"ViewController的优先级:%lf",[NSThread threadPriority]);

    NSLog(@"ViewController是否是主线程:%d",[[NSThread currentThread] isMainThread]);
}

-(void)cancelThread1:(NSThread*)thread{

    [thread cancel];

}
-(void)threadCallMethod{

    //(2)延迟2s,判断当前线程是否是被取消的状态.
    [NSThread sleepForTimeInterval:2];

    if ([[NSThread currentThread]isCancelled]) {

        //如果是,退出线程
        [NSThread exit];

    }

    NSLog(@"threadPriority的优先级:%lf",[NSThread threadPriority]);

    NSLog(@"threadCallMethod是否是主线程:%d",[[NSThread currentThread] isMainThread]);

}

@end

import “CustomThread.h”

@implementation CustomThread
-(void)test{

}
-(void)main{

NSLog(@"threadPriority的优先级:%lf",[NSThread threadPriority]);

NSLog(@"threadCallMethod是否是主线程:%d",[[NSThread currentThread] isMainThread]);

}


NSOperation的创建

import “ViewController.h”

import “CustomOperation.h”

@interface ViewController ()
{

NSInvocationOperation *cancelOperation;

}
@end

@implementation ViewController

  • (void)viewDidLoad {
    [super viewDidLoad];

    //初始化任务队列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];

    //设置队列的最大并发数
    queue.maxConcurrentOperationCount = 1;

    //queue 被挂起(暂停)
    queue.suspended = YES;

    //添加任务
    //case 1
    [queue addOperationWithBlock:^{

    NSLog(@"operation1");
    //队列中的任务是在子线程中执行的.
    

    // NSLog(@”%d”,[[NSThread currentThread]isMainThread]);

    }];

    //case 2
    //NSBlockOperation:能够并发的执行一个或者多个任务
    NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{

    for (int i =0; i<10; i++) {
    
        NSLog(@"operation2----%d",i);
    
    }
    

    }];
    //添加任务 和blockOperation的第一任务并发执行
    [blockOperation addExecutionBlock:^{

    NSLog(@"又执行了一个新的操作:线程:%@",[NSThread currentThread]);
    

    }];
    [blockOperation addExecutionBlock:^{

    NSLog(@"又执行了一个新的操作:线程:%@",[NSThread currentThread]);
    

    }];
    [blockOperation addExecutionBlock:^{

    NSLog(@"又执行了一个新的操作:线程:%@",[NSThread currentThread]);
    

    }];

    //监听blockOperation中的任务完成后,调用该block
    blockOperation.completionBlock=^(){

    NSLog(@"blockOperation的任务都完成了");
    

    };

    //将operation添加到queue
    [queue addOperation:blockOperation];

    //case 3
    NSInvocationOperation *invocationOp =[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(threadCallMethod) object:nil];
    [queue addOperation:invocationOp];

    //case 4 自定义operation
    CustomOperation *cusOp = [[CustomOperation alloc]init];

    //设置当前opration在queue中的优先级,优先级越大,越先执行.
    [cusOp setQueuePriority:NSOperationQueuePriorityVeryHigh];

    //addDependency:添加依赖关系(改变执行的顺序)
    //blockOperation依赖于invocationOp
    //必须等到invocationOp执行完毕后才可以执行blockOperation
    [blockOperation addDependency:invocationOp];

    [queue addOperation:cusOp];

    //取消任务
    cancelOperation = [[NSInvocationOperation alloc]initWithTarget:self selector: @selector(cancelOperationTask) object:nil];

    [queue addOperation:cancelOperation];

    //取消单个任务

    //(1)先将operation标记成cancel状态
    //(2)在任务执行的时候判断是否是cancel状态

// [self performSelector:@selector(cancelSingelOperation:) withObject:cancelOperation afterDelay:1];

//取消所有任务
[self performSelector:@selector(cancelallOperation:) withObject:queue afterDelay:1];
//关闭暂停
queue.suspended = NO;

}
-(void)cancelallOperation:(NSOperationQueue*)q{

//如果一个操作已经在执行,不会停止.

//队列取消所有的任务
[q cancelAllOperations];

}

-(void)cancelSingelOperation:(NSInvocationOperation*)op{

[op cancel];

}
-(void)cancelOperationTask{

[NSThread sleepForTimeInterval:2];
if (cancelOperation.isCancelled) {

    NSLog(@"cancelOperation is cancelled");
}else{

     NSLog(@"cancelOperation is executing");
}

}

-(void)threadCallMethod{

for (int i =0; i<10; i++) {

    NSLog(@"operation3----%d",i);

}

}
@end

import “CustomOperation.h”

@implementation CustomOperation

-(void)main{

for (int i =0; i<10; i++) {

    NSLog(@"operation4----%d",i);

}

}

@end

“`

四 .同步,异步,阻塞,非阻塞

名词解释:
- 队列:是先进先出(FIFO, First-In-First-Out)的线性表。通常用链表或者数组来实 现。队列只允许在后端(称为rear)进行插入操作,在前端(称为front)进行删除操作

  • 任务:具体要做的东西,比如方法调用等

  • 串行 xing(serial):使用一条数据线,将数据一位一位地依次传输,每一位数据占据一个固定的时间长度,指我们做任务时,一个一个步骤去执行

  • 并发(Concurrent):一个处理器同时处理多个任务。并发事件之间不一定要同一 时刻发生,指逻辑上的同时发生

  • 并行( parallel):多个处理器或多核处理器同时处理多个不同的任务。同时发生的 两个并发事件,具有并发的含义,而并发则不一定并行,指物理上的同时发生。

  • 同步:调用者调用一个任务开始执行后,调用者得等待 拿到了结果 才会继续往下执 行

  • 异步:调用者调用一个任务开始执行后,调用者不用等待 拿到结果,会继续往下执行。 实际上任务执行完成后会通知调用者

  • 阻塞:指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回

  • 非阻塞:指不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回

  • 死锁:是指两个或两个以上的线程在执行过程中,由于竞争资源或者由于彼此通信而 造成的一种阻塞的现象

  • 互斥锁:多线程编程中,防止两条线程同时对同一公共资源(比如全局变量)进行读 写的机制

  • 信号量:又称为信号灯,是一个计数器,它用来记录对某个资源(如共享内存)的存 取状况

    这里写图片描述
    这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值