您的位置:首页 > 产品设计 > UI/UE

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

2016-08-04 21:32 351 查看

一.线程与进程

进程与线程的理解:

- 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{

}

-(voi
b5f5
d)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):多个处理器或多核处理器同时处理多个不同的任务。同时发生的 两个并发事件,具有并发的含义,而并发则不一定并行,指物理上的同时发生。

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

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

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

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

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

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

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



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息