了解多线程之前首先要了解一下几个概念
进程
进程是指在系统中正在进行的一个应用程序;每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内。
线程
一个进程要想执行任务,必须得有线程(每一个进程至少要有一条线程),是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位;
多线程
进程中可以开启多条线程,每条线程可以并行(同时)执行不同的任务。多线程技术可以提高程序的执行效率。
多线程原理
单核CPU同一时间内能处理1条线程,多线程并发执行,其实是CPU快速地在多条线程之间调度。如果CPU调度线程的时间足够快,就造成了多线程并发执行的假象。
多线程的优缺点
优点:能适当提高程序的执行效率;能适当提高资源利用率(CPU、内存利用率)。
缺点:开启线程需要占用一定的内存空间(默认情况下,主线程占用1M,子线程占用512KB),如果开启大量的线程,会占用大量的内存空间,降低程序的性能;线程越多,CPU在调度线程上的开销就越大;程序设计更加复杂,例如线程之间的通信、多线程的数据共享。
同步和异步的区别
同步:只能在当前线程中执行任务,不具备开启新线程的能力
异步:可以在新的线程中执行任务,具备开启新线程的能力
并发和串行
并发:多个任务并发(同时)执行
串行:一个任务执行完毕后,再执行下一个任务
线程间怎么通信
NSThread
[self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:NO];
- (void)updateUI {
// UI更新代码
self.alert.text = @"Thanks!";
}
NSOperationQueue
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// UI更新代码
self.alert.text = @"Thanks!";
}];
GCD
dispatch_async(dispatch_get_main_queue(), ^{
// UI更新代码
self.alert.text = @"Thanks!";
});
多线程在ios中的运用
1499394732413995.pngNSThread的使用
NSThread创建线程
/** 方法一,需要start */
NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(doSomething1:) object:@"NSThread1"];
// 线程加入线程池等待CPU调度,时间很快,几乎是立刻执行
[thread1 start];
- (void)doSomething1:(NSObject *)object {
// 传递过来的参数
NSLog(@"%@",object);
NSLog(@"doSomething1:%@",[NSThread currentThread]);
}
/** 方法二,创建好之后自动启动 */
[NSThread detachNewThreadSelector:@selector(doSomething2:) toTarget:self withObject:@"NSThread2"];
- (void)doSomething2:(NSObject *)object {
NSLog(@"%@",object);
NSLog(@"doSomething2:%@",[NSThread currentThread]);
}
/** 方法三,隐式创建,直接启动 */
[self performSelectorInBackground:@selector(doSomething3:) withObject:@"NSThread3"];
- (void)doSomething3:(NSObject *)object {
NSLog(@"%@",object);
NSLog(@"doSomething3:%@",[NSThread currentThread]);
}
返回当前线程
// 当前线程
[NSThread currentThread];
NSLog(@"%@",[NSThread currentThread]);
阻塞休眠
//休眠多久
[NSThread sleepForTimeInterval:2];
//休眠到指定时间
[NSThread sleepUntilDate:[NSDate date]];
其他一些方法
//退出线程
[NSThread exit];
//判断当前线程是否为主线程
[NSThread isMainThread];
//判断当前线程是否是多线程
[NSThread isMultiThreaded];
//主线程的对象
NSThread *mainThread = [NSThread mainThread];
GCD的理解与使用
GCD中有2个核心概念
(1)任务:执行什么操作
(2)队列:用来存放任务
队列
不管是什么队列,一定是FIFO队列,即先进先出。
所以,请大家记住了:不管是串行队列(SerialQueue)还是并发队列(ConcurrencyQueue),都是FIFO队列。也就意味着,任务一定是一个一个地,按照先进先出的顺序来执行。
串行队列:
在创建队列时,传参数DISPATCH_QUEUE_SERIAL表示创建串行队列。任务会一个一个地执行,只有前一个任务执行完成,才会继续执行下一个任务。串行执行并不是同步执行的意思,一定要注意区分。
并发队列:
在创建队列时,传参数DISPATCH_QUEUE_CONCURRENT表示创建并发队列。并发队列会尽可能多地创建线程去执行任务。并发队列中的任务会按入队的顺序执行任务,但是哪个任务先完成是不确定的。
串行队列
dispatch_queue_t serialQueue = dispatch_queue_create("serial_queue",
DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
NSLog(@"s1");
});
dispatch_async(serialQueue, ^{
sleep(2);
NSLog(@"s2");
});
dispatch_async(serialQueue, ^{
sleep(1);
NSLog(@"s3");
});
打印 s1,s2,s3
并发队列
dispatch_queue_t concurrencyQueue = dispatch_queue_create("com.huangyibiao.concurrency-queue",
DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrencyQueue, ^{
NSLog(@"s1");
});
dispatch_async(concurrencyQueue, ^{
sleep(2);
NSLog(@"s2");
});
dispatch_async(concurrencyQueue, ^{
sleep(1);
NSLog(@"s3");
});
打印 s1,s3,s2
同步异步线程
// 全局并发队列的获取方法
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 同步执行任务创建方法
dispatch_sync(queue, ^{
// 这里放同步执行任务代码
});
// 异步执行任务创建方法
dispatch_async(queue, ^{
// 这里放异步执行任务代码
});
网友评论