ios 多线程你需要了解的

2018-08-16  本文已影响11人  赵哥窟

了解多线程之前首先要了解一下几个概念

进程

进程是指在系统中正在进行的一个应用程序;每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内。

线程

一个进程要想执行任务,必须得有线程(每一个进程至少要有一条线程),是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位;

多线程

进程中可以开启多条线程,每条线程可以并行(同时)执行不同的任务。多线程技术可以提高程序的执行效率。

多线程原理

单核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.png
NSThread的使用

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, ^{
    // 这里放异步执行任务代码
});
上一篇下一篇

猜你喜欢

热点阅读