版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lianjiaokeji/article/details/83095187
1.进程的概念
一个CPU的时候运行,轮询调度实现并发执行
多CPU运行机制:
计算机程序:存储在磁盘上的可执行二进制(或其他类型)文件。
只有把它们加载到内存中,并被操作系统调用它们才会拥有其自己的生命周期。
进程:表示的一个正在执行的程序。
每个进程都拥有自己的地址空间、内存、数据栈以及其他用于跟踪执行的辅助数据
操作系统负责其上所有进程的执行,操作系统会为这些进程合理地分配执行时间。
多进程测试
使用多进程测试代码必须两核以上(相当于多个CPU同时运行)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2018/10/13 16:26
# @Author : DoubleChina
# @Site :
# @File : ThreadTest.py
# @Software: PyCharm
import time
import multiprocessing
import os # 系统模块
def func():
time.sleep(3)
i = 0
for j in range(1000):
i += 1
return True
def main():
start_time = time.time()
# 创建一个子进程,进程对象
p = multiprocessing.Process(target=func)
# 获取当前进程的名字
# multiprocessing.current_process()
# 判断这个进程实例,是否还在运行
# p.is_alive()
# 不管这个是否在运行,强制杀掉
# p.terminate()
# 默认值False,主进程
p.daemon = True
# join 等待这个进程结束,主进程才结束
# p.join()
# 启动进程
p.start()
func()
end_time = time.time()
print("子进程:", end_time - start_time)
def get_pid():
# linux独有的,window上没有
# linux创建进程,是操作系统把父进程的东西拷贝到子进程,复制进程
# windows创建进程,类似于模块导入的方法,一定要写main方法,要不会出现执行多次
pid = os.fork()
if pid == 0: # 子进程永远返回的是0
print('子进程{},父进程{}'.format(os.getpid(), os.getppid()))
else: # 父进程返回的是子进程的id
print('父进程{},子进程{}'.format(os.getpid(), pid))
def main1():
start_time = time.time()
func()
func()
end_time = time.time()
print(end_time - start_time)
class BolockProcess(multiprocessing.Process):
def __init__(self):
super().__init__()
def run(self):
n = 5
while n > 0:
print('the time is{}'.format(time.ctime()))
time.sleep(2)
n -= 1
def test_BolockProcess(): # 对象继承
for i in range(5):
p = BolockProcess()
p.start()
if __name__ == '__main__':
# start_time = time.time()
# main()
# end_time = time.time()
# print("主进程:", end_time - start_time)
# main1()
# get_pid()
test_BolockProcess()
单进程运行时间:
22.23472023010254秒
多进程运行速度:
11.984376192092896秒
多进程调用流程:
计算密集型:在python中,计算密集型用多进程
IO密集型:爬虫典型的IO密集型,用多线程,但是在python中多线程GIL槽糕的设计,比单线程整整慢了45%,但是在Python3以后已经优化了。
2.多线程
线程被称作轻量级进程。
与进程类似,不过它们是在同一个进程下执行的,并且它们会共享相同的上下文。
- 当其他线程运行时,它可以被抢占(中断)
- 和临时挂起(也成为睡眠) — 让步
线程的轮训调度机制类似于进程的轮询调度。
只不过这个调度不是由操作系统来负责,而是由Python解释器来负责。
多线程方法详解
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2018/10/13 16:26
# @Author : DoubleChina
# @Site :
# @File : ThreadTest.py
# @Software: PyCharm
import time
import threading
def func():
i = 0
for j in range(100000000):
i += 1
return True
def main():
start_time = time.time()
# 创建一个子进程
p = threading.Thread(target=func)
# 线程守护
p.setDaemon(True)
# 设置线程名称
p.setName("线程1")
# 获取线程名称
p.getName()
p.start()
func()
end_time = time.time()
print(end_time - start_time)
def main1():
start_time = time.time()
func()
func()
end_time = time.time()
print(end_time - start_time)
class MyThread(threading.Thread):
def __init__(self, name):
super().__init__()
self.name = name
def run(self):
time.sleep(2)
print('I am is{}'.format(self.name))
if __name__ == '__main__': # 一个文件如果是自己执行 __name__就是main
# 22.1539466381073秒
# GIL锁,线程使用在3.6以后有大版本的优化
# main()
# 23.165987253189087秒
# main1()
thread_list = []
start_time = time.time()
for i in range(100):
t = MyThread('线程{}号'.format(i))
# 线程守护,主线程结束,子线程也会全部关掉
t.setDaemon(True)
t.start()
# 线程id
t.ident
thread_list.append(t)
# for t in thread_list:
# 等待子线程结束,主线程阻塞的作用
# t.join()
end_time = time.time()
print(end_time - start_time)
GIL锁
Python在设计的时候,还没有多核处理器的概念。
因此,为了设计方便与线程安全,直接设计了一个锁。
这个锁要求,任何进程中,一次只能有一个线程在执行。
因此,并不能为多个线程分配多个CPU。所以Python中的线程只能实现并发,而不能实现真正的并行。
但是Python3中的GIL锁有一个很棒的设计,在遇到阻塞(不是耗时)的时候,会自动切换线程。
多线程处理Socket并发
服务器:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2018/10/13 21:56
# @Author : DoubleChina
# @Site :
# @File : ThreadSocket.py
# @Software: PyCharm
import socket
import threading
server = socket.socket()
server.bind(('', 9999))
server.listen(5)
def readThread(conn, addr):
"""
创建一个新的线程,负责和一个客户端通讯
:param conn:
:param addr:
:return:
"""
while True:
data = conn.recv(1024)
if data:
print('{}:{}'.format(addr, data))
else:
print("客户端{}已关闭".format(addr))
break
conn.close()
while True:
print('------主线程,等待客户端连接------')
conn, addr = server.accept()
print('创建一个新的线程,和客户端{}通讯'.format(addr))
# 创建一个子线程,负责消息收发
client = threading.Thread(target=readThread, args=(conn, addr))
# 启动线程
client.start()
客户端:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2018/10/13 7:38
# @Author : DoubleChina
# @Site :
# @File : SocketTest.py
# @Software: PyCharm
import socket
# 创建套接字
s = socket.socket()
# 连接套接字,ip和端口必须是服务器上的
s.connect(('127.0.0.1', 9999))
while True:
data = input("输入发送消息:")
if 'q' == data:
s.close()
break
s.send(data.encode())
# print('接受服务器返回的消息:', s.recv(1024))
# s.close()
多进程处理Socket并发
服务器:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2018/10/13 21:56
# @Author : DoubleChina
# @Site :
# @File : ThreadSocket.py
# @Software: PyCharm
import socket
import threading
import multiprocessing
server = socket.socket()
server.bind(('', 9999))
server.listen(5)
def readProcess(conn, addr):
"""
创建一个新的线程,负责和一个客户端通讯
:param conn:
:param addr:
:return:
"""
while True:
data = conn.recv(1024)
if data:
print('{}:{}'.format(addr, data))
else:
print("客户端{}已关闭".format(addr))
break
conn.close()
while True:
print('------主线程,等待客户端连接------')
conn, addr = server.accept()
print('创建一个新的进程,和客户端{}通讯'.format(addr))
# 创建一个子进程
p = multiprocessing.Process(target=readProcess, args=(conn, addr))
p.start()