程序是由什么构成的,可能有的人会说,它是有一个个字符和逻辑共同构成的,这个说法并不完全。
程序在没有运行的状态下,是一堆代码构成的。
运行的程序是由进程程构成的,进程是程序执行的基本单位。对于进程,它可以又多个不同的线程共同构成,线程在程序中是如何运行的,他们运行的方式和关系。
同步执行和异步执行、串行队列和并发队列的核心是:任务和队列。
任务:就是执行操作,换句话说就是你在线程中执行的那段代码。
同步执行:
- 同步执行(Sync):
1) 同步添加任务到指定的队列中,在添加的任务执行结束之前,会一直等待,直到队列里面的任务完成之后再
- 异步执行(Async):
1)异步添加任务到指定的队列中,它不会做任何等待,可以继续执行任务
2)可以在新的线程中执行任务,具备开启新线程的能力。
同步执行和异步执行、串行队列和并发队列的核心是:任务和队列。
1)同步执行和异步执行的核心: 任务
区别: 是否等待队列的任务执行结束,以及是否具备开启新线程的能力
串行队列和并发队列的核心: 队列
相同: 串行队列和并发队列都符合FIFO(先进先出)的原则。
区别: 执行的顺序不同,以及开启的线程数不同
(备注:并发队列的并发功能只能在异步函数下才有效)
下边使用OC中的GCD来展示以下四种组合出现的情况:
1.同步执行 + 串行队列:
2.异步执行 + 串行队列:
3.同步执行 + 并发队列:
4.异步执行 + 并发队列:
1.同步执行 + 串行队列:
//同步执行 + 串行队列
-(void)syncSerial{
NSLog(@"CurrentThread ------%@",[NSThread currentThread]);
NSLog(@"syncSerial------Begin");
dispatch_queue_t queue = dispatch_queue_create("SerialTest", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
// 添加任务1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"1----------%@", [NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
// 添加任务2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"2----------%@", [NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
// 添加任务3
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"3----------%@", [NSThread currentThread]);
}
});
NSLog(@"syncSerial------------end");
}
执行结果:
2018-03-21 10:57:36.273782+0800 ThreadTest[2057:2142420] CurrentThread ------<NSThread: 0x604000078fc0>{number = 1, name = main}
2018-03-21 10:57:36.273961+0800 ThreadTest[2057:2142420] syncSerial------Begin
2018-03-21 10:57:38.274892+0800 ThreadTest[2057:2142420] 1----------<NSThread: 0x604000078fc0>{number = 1, name = main}
2018-03-21 10:57:40.275845+0800 ThreadTest[2057:2142420] 1----------<NSThread: 0x604000078fc0>{number = 1, name = main}
2018-03-21 10:57:42.277407+0800 ThreadTest[2057:2142420] 2----------<NSThread: 0x604000078fc0>{number = 1, name = main}
2018-03-21 10:57:44.278935+0800 ThreadTest[2057:2142420] 2----------<NSThread: 0x604000078fc0>{number = 1, name = main}
2018-03-21 10:57:46.279713+0800 ThreadTest[2057:2142420] 3----------<NSThread: 0x604000078fc0>{number = 1, name = main}
2018-03-21 10:57:48.281338+0800 ThreadTest[2057:2142420] 3----------<NSThread: 0x604000078fc0>{number = 1, name = main}
2018-03-21 10:57:48.281630+0800 ThreadTest[2057:2142420] syncSerial------------end
2.异步执行 + 串行队列:
// 异步并发 + 串行队列
-(void)asyncSerial{
NSLog(@"Current Thread:-------%@",[NSThread currentThread]);
NSLog(@"asyncSerial--------begin");
dispatch_queue_t queue = dispatch_queue_create("asyncSerialTest", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
// 添加任务1
for (int i = 0; i < 2 ; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"1--------------%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
// 添加任务2
for (int i = 0; i < 2 ; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"2--------------%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
// 添加任务3
for (int i = 0; i < 2 ; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"3--------------%@",[NSThread currentThread]);
}
});
}
2018-03-21 11:01:03.131755+0800 ThreadTest[2172:2144740] Current Thread:-------<NSThread: 0x60400006f500>{number = 1, name = main}
2018-03-21 11:01:03.131923+0800 ThreadTest[2172:2144740] asyncSerial--------begin
2018-03-21 11:01:05.135621+0800 ThreadTest[2172:2144804] 1--------------<NSThread: 0x604000279bc0>{number = 3, name = (null)}
2018-03-21 11:01:07.137982+0800 ThreadTest[2172:2144804] 1--------------<NSThread: 0x604000279bc0>{number = 3, name = (null)}
2018-03-21 11:01:09.143012+0800 ThreadTest[2172:2144804] 2--------------<NSThread: 0x604000279bc0>{number = 3, name = (null)}
2018-03-21 11:01:11.146212+0800 ThreadTest[2172:2144804] 2--------------<NSThread: 0x604000279bc0>{number = 3, name = (null)}
2018-03-21 11:01:13.147072+0800 ThreadTest[2172:2144804] 3--------------<NSThread: 0x604000279bc0>{number = 3, name = (null)}
2018-03-21 11:01:15.151203+0800 ThreadTest[2172:2144804] 3--------------<NSThread: 0x604000279bc0>{number = 3, name = (null)}
3.同步执行 + 并发队列:
// 同步执行 + 并发队列
//
-(void)syncConcurrent{
NSLog(@"currentThread-----%@",[NSThread currentThread]);
NSLog(@"syncConcurrent----begin");
// 创建一个并发队列
dispatch_queue_t queue = dispatch_queue_create("testQueue", DISPATCH_QUEUE_CONCURRENT);
//并发队列中 添加 同步执行任务
dispatch_sync(queue, ^{
// 追加任务1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:1];
NSLog(@"1-------%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
// 追加任务2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:1];
NSLog(@"2--------%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
// 追加任务3
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:1];
NSLog(@"3---------%@", [NSThread currentThread]);
}
});
NSLog(@"syncConcurrent -------- end");
}
2018-03-21 11:02:20.648393+0800 ThreadTest[2227:2145966] currentThread-----<NSThread: 0x600000076b80>{number = 1, name = main}
2018-03-21 11:02:20.648628+0800 ThreadTest[2227:2145966] syncConcurrent----begin
2018-03-21 11:02:21.649938+0800 ThreadTest[2227:2145966] 1-------<NSThread: 0x600000076b80>{number = 1, name = main}
2018-03-21 11:02:22.650266+0800 ThreadTest[2227:2145966] 1-------<NSThread: 0x600000076b80>{number = 1, name = main}
2018-03-21 11:02:23.650869+0800 ThreadTest[2227:2145966] 2--------<NSThread: 0x600000076b80>{number = 1, name = main}
2018-03-21 11:02:24.651351+0800 ThreadTest[2227:2145966] 2--------<NSThread: 0x600000076b80>{number = 1, name = main}
2018-03-21 11:02:25.652397+0800 ThreadTest[2227:2145966] 3---------<NSThread: 0x600000076b80>{number = 1, name = main}
2018-03-21 11:02:26.653781+0800 ThreadTest[2227:2145966] 3---------<NSThread: 0x600000076b80>{number = 1, name = main}
2018-03-21 11:02:26.654109+0800 ThreadTest[2227:2145966] syncConcurrent -------- end
// 异步执行 + 并发队列
//特点:
-(void)asyncConcurrent{
NSLog(@"asyncConcurrent ----%@ ",[NSThread currentThread]);
NSLog(@"AsyncConcurrent----begin");
// 创建并发队列
dispatch_queue_t quenue = dispatch_queue_create("quenueTest", DISPATCH_QUEUE_CONCURRENT);
// 并发队列中添加异步执行任务
dispatch_async(quenue, ^{
//追加任务1
for (int i = 0; i<2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"1---------%@",[NSThread currentThread]);
}
});
dispatch_async(quenue, ^{
//追加任务2
for (int i = 0; i<2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"2---------%@",[NSThread currentThread]);
}
});
dispatch_async(quenue, ^{
//追加任务3
for (int i = 0; i<2; ++i) {
[NSThread sleepForTimeInterval:2];
NSLog(@"3---------%@",[NSThread currentThread]);
}
});
}
2018-03-21 11:03:24.971218+0800 ThreadTest[2278:2147177] asyncConcurrent ----<NSThread: 0x604000073740>{number = 1, name = main}
2018-03-21 11:03:24.971412+0800 ThreadTest[2278:2147177] AsyncConcurrent----begin
2018-03-21 11:03:26.976195+0800 ThreadTest[2278:2147265] 3---------<NSThread: 0x604000271480>{number = 4, name = (null)}
2018-03-21 11:03:26.976195+0800 ThreadTest[2278:2147267] 1---------<NSThread: 0x604000268f40>{number = 3, name = (null)}
2018-03-21 11:03:26.976225+0800 ThreadTest[2278:2147266] 2---------<NSThread: 0x604000271500>{number = 5, name = (null)}
2018-03-21 11:03:28.980970+0800 ThreadTest[2278:2147266] 2---------<NSThread: 0x604000271500>{number = 5, name = (null)}
2018-03-21 11:03:28.980980+0800 ThreadTest[2278:2147267] 1---------<NSThread: 0x604000268f40>{number = 3, name = (null)}
2018-03-21 11:03:28.980987+0800 ThreadTest[2278:2147265] 3---------<NSThread: 0x604000271480>{number = 4, name = (null)}
线程:
时间:线程在时间上可以分为“串行” 和“并发”两种方式,同步就是让我们的线程同时执行,异步线程不同时执行。强调时间性。
关系:线程在线程之间关系上可以分为“顺序执行”和“并行执行”,强调的是线程之间的关系。
线程在执行的过程中,线程可以分为四种:
同步执行 + 串行队列:我们把任务分配一个个线程,每个线程的任务都在主线程中执行。
异步执行 + 串行队列:队列中的任务顺序执行:在子线程中执行,主线程继续,不会等待子线程执行完毕。
同步执行 + 并发队列:(一般不用):队列中任务顺序执行,在主线程中执行(并行)
异步执行 + 并发队列:队列中的任务同时执行;在子线程中执行;主线程继续执行,不会等待子线程执行完毕。
线程同步和异步之间的关系
同步:多个线程在同一时间同时执行。
异步:多个线程在不同时间被执行。
在多线程的执行过程中,线程之间的数据的传递、共享会存在已写小的问题,我们需要对线程进行加锁/解锁操作,对线程进行操作,达到对程序设计的目标。
每个运行中的程序都对应一个进程,每个进程可能可能由多个线程共同组成。