「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战」
进程与线程
什么是进程
进程是系统中正在运行的一个程序,程序一旦运行就是进程。
什么是线程
线程是进程中执行运算的最小单位,负责当前进程中程序的执行。
进程与线程的关系。
一个进程至少有一个线程,一个进程可以运行多个线程,同一进程的多个线程可共享数据。
进程与线程的区别
进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位。
线程与队列
线程与队列的关系
队列是用于保存以及管理任务的,线程负责去队列中取任务进行执行。也可以理解为队列调度任务给到线程中执行。
主线程
iOS中为什么刷新UI是在主线程中呢?
因为UIKit框架不是线程安全的,当多个线程同时操作UI的时候,可能会出现抢夺资源、读写问题,导致崩溃,UI异常等问题。
队列
队列是一种先进先出的数据结构,是一个特殊的线性表,也就是我们说的FIFO,我们也可以理解为排队。
串行队列:只开启一个线程,每次只能有一个任务执行,等待执行完毕后才会执行下一个任务。其中主队列也是一种特殊的串行队列,主队列的任务是在主线程中执行。
并发队列:可以让对个任务同时执行,也就是开启多个线程,让多个任务同时执行。我们简单理解就是并发队列有任务A和B,任务A交给线程A执行,如果是异步调度,这时候不用等任务A完成,任务B就可以交给线程B执行。其中全局队列也是一种并发队列。
任务
任务就是执行代码的操作。任务的执行方式有同步执行和异步执行。
同步执行:在当前线程中执行任务,任务没有执行完毕之前是不会执行下一个任务,而且只能在一个线程中执行,所以我们说同步操作会堵塞线程。不具备开启线程能力。
异步执行:在新的线程中执行任务,添加任务的时候会立即返回,不会堵塞线程,具备开启线程能力。
同步串行
dispatch_queue_t queue = dispatch_queue_create( "jj.com" , DISPATCH_QUEUE_SERIAL);
for ( int i = 0; i < 5; i++) {
dispatch_sync(queue, ^{
if (i == 2) {
sleep(2);
}
NSLog (@ "%@ %d" , [ NSThread currentThread], i);
});
}
NSLog (@"同步串行完成");
我们看下同步串行输出结果:
2022-02-13 22:45:58.590740+0800 多线程[61384:1124644] <_NSMainThread: 0x600001f9c300>{number = 1, name = main} 0
2022-02-13 22:45:58.591959+0800 多线程[61384:1124644] <_NSMainThread: 0x600001f9c300>{number = 1, name = main} 1
2022-02-13 22:46:00.593617+0800 多线程[61384:1124644] <_NSMainThread: 0x600001f9c300>{number = 1, name = main} 2
2022-02-13 22:46:00.594050+0800 多线程[61384:1124644] <_NSMainThread: 0x600001f9c300>{number = 1, name = main} 3
2022-02-13 22:46:00.594434+0800 多线程[61384:1124644] <_NSMainThread: 0x600001f9c300>{number = 1, name = main} 4
2022-02-13 22:46:00.594847+0800 多线程[62708:1130460] 同步串行完成
同步串行:可以看到打印顺序是是按正常顺序执行,当前方法是在主线程中执行,可以看到name=main也是在主线程中执行,也就是说不具备开启线程能力,并且执行任务是一个执行完后,再执行另外一个任务。最后打印同步串行完成也是能表面同步堵塞了主线程。
同步并发
dispatch_queue_t queue = dispatch_queue_create( "jj.com" , DISPATCH_QUEUE_CONCURRENT);
for ( int i = 0; i< 5; i++) {
dispatch_sync(queue, ^{
if (i == 2) {
sleep(2);
}
NSLog (@ "%@ %d" , [ NSThread currentThread], i);
});
}
NSLog (@"同步并发完成");
我们看下同步并发输出结果:
2022-02-13 23:00:07.548954+0800 多线程[65378:1141271] <_NSMainThread: 0x600003fb0280>{number = 1, name = main} 0
2022-02-13 23:00:07.549225+0800 多线程[65378:1141271] <_NSMainThread: 0x600003fb0280>{number = 1, name = main} 1
2022-02-13 23:00:09.550559+0800 多线程[65378:1141271] <_NSMainThread: 0x600003fb0280>{number = 1, name = main} 2
2022-02-13 23:00:09.550822+0800 多线程[65378:1141271] <_NSMainThread: 0x600003fb0280>{number = 1, name = main} 3
2022-02-13 23:00:09.551005+0800 多线程[65378:1141271] <_NSMainThread: 0x600003fb0280>{number = 1, name = main} 4
2022-02-13 23:00:09.551148+0800 多线程[65378:1141271] 同步并发完成
同步并发:可以看到打印顺序是是按正常顺序执行,当前方法是在主线程中执行,可以看到name=main也是在主线程中执行,也就是说不具备开启线程能力,并且执行任务是一个执行完后,再执行另外一个任务。最后打印同步并发完成也是能表面同步堵塞了主线程。
异步串行
dispatch_queue_t queue = dispatch_queue_create( "jj.com" , DISPATCH_QUEUE_SERIAL);
for ( int i = 0; i< 5; i++) {
dispatch_async(queue, ^{
if (i == 2) {
sleep(2);
}
NSLog (@ "%@ %d" , [ NSThread currentThread], i);
});
}
NSLog (@"异步串行完成");
我们看下异步串行输出结果:
2022-02-13 22:53:23.211533+0800 多线程[63472:1133783] 异步串行完成
2022-02-13 22:53:23.211599+0800 多线程[63472:1133869] <NSThread: 0x6000025d47c0>{number = 4, name = (null)} 0
2022-02-13 22:53:23.211821+0800 多线程[63472:1133869] <NSThread: 0x6000025d47c0>{number = 4, name = (null)} 1
2022-02-13 22:53:25.212448+0800 多线程[63472:1133869] <NSThread: 0x6000025d47c0>{number = 4, name = (null)} 2
2022-02-13 22:53:25.212864+0800 多线程[63472:1133869] <NSThread: 0x6000025d47c0>{number = 4, name = (null)} 3
**2022-02-13 22:53:25.213017+0800 多线程[63472:1133869] <NSThread: 0x6000025d47c0>{number = 4, name = (null)} 4
异步串行:由上面结果,先走异步串行完成,说明异步是不堵塞线程的,我们是在主线程执行代码的,看打印可以看到number = 4,说明异步串行是开启了新的线程(异步主队列是主线程中执行,不开启新线程)。
异步并发
dispatch_queue_t queue = dispatch_queue_create( "jj.com" , DISPATCH_QUEUE_CONCURRENT);
for ( int i = 0; i< 5; i++) {
dispatch_async(queue, ^{
if (i == 2) {
sleep(2);
}
NSLog (@ "%@ %d" , [ NSThread currentThread], i);
});
}
NSLog (@"异步并发完成");
我们看下异步并发输出结果:
2022-02-13 23:22:47.019240+0800 多线程[2262:18916] 异步并发完成
2022-02-13 23:22:47.019361+0800 多线程[2262:21091] <NSThread: 0x600003511780>{number = 5, name = (null)} 3
2022-02-13 23:22:47.019361+0800 多线程[2262:21093] <NSThread: 0x6000035117c0>{number = 6, name = (null)} 0
2022-02-13 23:22:47.019405+0800 多线程[2262:21095] <NSThread: 0x600003510bc0>{number = 3, name = (null)} 1
2022-02-13 23:22:47.019537+0800 多线程[2262:21091] <NSThread: 0x600003511780>{number = 5, name = (null)} 4
2022-02-13 23:22:49.023048+0800 多线程[2262:21094] <NSThread: 0x600003542a40>{number = 2, name = (null)} 2
异步并发:先打印异步并发完成说明不会堵塞当前线程,打印的number各不相当,也就是说异步并发会开启新的线程,并且会并发执行任务,i==2时sleep2秒,并不会影响到其它任务执行。