进程线程概念
进程理解为一个程序, 具体完成工作的是线程. 比如说启动一个 QQ ,QQ 程序里面可以聊天, 设置, 查找好友等, 那么这些功能就理解成各个线程, 也就是单进程多线程的一个模式. 进程理解成人脑子, 线程理解成人的手, 只有脑子是无法完成工作, 必须要有手. 所以启动进程下面一定是有一个线程, 可以理解成主线程, 且线程之间是互相不影响的.
那么一个计算机的最大并发进程数是多少呢? 我这里说的并发是指的是真正的并发, 并发数就等于电脑的核心数, 比如说电脑的 CPU 核心数为 8 个, 那么就是最大能并发 8 个进程.
多线程 --threading
1, 启动多线程
比如我们 pycharm , 运行一个 .py 文件, 实际上就是运行一个程序, 这个程序就是个进程, 但是进程内是线程在运行结果. 那么我们的进程默认下只有 1 个线程, 怎么增加单进程下的线程数呢? 需要引用到模块 -- threading , 比如说启动 10 个线程来帮我们执行一个程序 10 次:
- import threading
- import time
- def eat():
- time.sleep(1)
- print('吃饭')
- start_time = time.time()
- for i in range(10):
- t = threading.Thread(target=eat) #实例化了一个线程, 这里面不要写成 eat() , 写成 eat() 就不是多线程了
- t.start()# 运行这个线程
- end_time = time.time()
- print('运行的时间',end_time - start_time)
结果:
运行的时间 0.002976655960083008
吃饭吃饭
吃饭吃饭
吃饭吃饭
吃饭
吃饭
吃饭
吃饭
上边的程序, 我们循环创建出了 10 个线程, 10 个线程去执行这个 eat() 方法, 且 eat() 方法内, 写了一个延时, 按照理解来讲, 程序的运行时间应该为 1s 左右 (因为多线程理解成广义并发执行 10 次 eat()), 但是结果却是: 运行时间连 1s 都不到, 这是为什么呢? 另外, 运行结果运行时间是在 eat() 方法之前打印出来的, 但是程序内我们的运行时间是在最后打印, 按理解程序应该从上至下执行, 为什么会出现该情况呢?
其实, 我们这里要好好理解一下, 刚刚我们的进程下是有几个线程?
答案应该是 1+10 = 11 个, 另外的那个进程其实是执行除 10 个线程之外的 1 个主线程, 这 11 个线程是并行执行, 而打印开始和结束时间是在那 1 个主线程之内的, 线程之间现在不会相互影响, 也就是说主线程只是执行到了
for i in range(10): 然后直接往下走, 子线程执行 eat() 并没有包含在主线程内, 所有说打印出时间不到 1s.
2, 等待子线程
那么, 如果需要统计出子线程运行完的时间要怎么办? 注意这里的子线程运行完的时间是指从所有子线程执行的最开始时间, 到所有子线程执行完成的时间最大长度. 把子线程理解成一大把筷子, 筷子有长有短, 且并没有顶端对其, 我们要量的长度是这把筷子的影子长度, 就这么理解. 也可以理解成, 我是主线程, 找 10 个人一起帮我干活, 我去外面休息, 等做好了叫我, 来统计时间
要实现这种做法, 是要在开辟子线程, 且子线程执行期间, 主线程不往下执行, 直到所有的子线程执行完毕, 主线程往下执行. 就可以统计到时间, 那么怎么做?
利用 .join() 方法, 就是让线程阻塞的意思, 但是下面的结果是 10s, 咦, 为啥变成串行的了?
- for i in range(10):
- t = threading.Thread(target=eat) #实例化了一个线程
- t.start()# 运行这个线程
- t.join()# 主线程会等待子线程结束
结果: 运行的时间 10.008797645568848
因为我们的 join 是写在循环内部, 比如启动一个子线程 1 , 那么主线程就等 1 执行完成, 完成后再启动一个子线程 2 , 主线程继续等待...... 也就是说主线程是等待所有的子线程依次完成, 也就是串行的方式. 也就是 1 个人找 10 个人干活, 是先让第一个人干完走, 再让第二个人干完走, 并不是 10 个人一起干. 也就是每次等待 1 个线程
那怎么实现等待所有子线程?
- import threading
- import time
- def eat():
- time.sleep(1)
- print('吃饭')
- # 将所有子线程装入一个 list
- threads = []
- start_time = time.time()
- for i in range(10):
- t = threading.Thread(target=eat) #实例化了一个线程, 这里面不要写成 eat() , 写成 eat() 就不是多线程了
- t.start()# 运行这个线程
- threads.append(t)
- for thread in threads: #循环等待子线程
- thread.join()
- end_time = time.time()
- print('运行的时间',end_time - start_time)
结果:
运行的时间 0.002935647964477539
吃饭
吃饭
吃饭
吃饭
吃饭
吃饭
吃饭
吃饭
吃饭
吃饭
另一种方式: 利用 while 判断是否只存在 1 个线程, 1 个线程才往下执行
- import threading
- import time
- def eat():
- time.sleep(1)
- print('吃饭')
- start_time = time.time()
- for i in range(10):
- t = threading.Thread(target=eat) #实例化了一个线程, 这里面不要写成 eat() , 写成 eat() 就不是多线程了
- t.start()# 运行这个线程
- print(threading.active_count()) #当前的线程数
- while threading.active_count()!=1: #判断当前程序里面是否只有主线程
- pass
- print(threading.active_count()) #当前的线程数
- end_time = time.time()
- print('运行的时间',end_time - start_time)
结果:
运行的时间 0.00247955322265625
11
吃饭吃饭吃饭
吃饭
吃饭
吃饭
吃饭
吃饭
吃饭
吃饭
1
多进程
来源: http://www.bubuko.com/infodetail-3080060.html