多进程
进程(process)是操作系统分配内存的基本单位
之间的内存是相互隔离的 如果要通讯要靠IPCG制(是很麻烦的)
原因1:
如果一个任务的执行时间较长,可以分配若干个小任务从而
提升执行效率 缩短执行时间
原因2:
改善用户体验
如果多个任务之间没有任何关联 而且希望利用cpu的多核特性
那么我们推荐使用多进程
information technology IT
摩尔定律 ——
安迪比尔定律(硬件的提升 软件也会把它运用起来 所以被软件的提升给抵消了)
反摩尔定律 —— 要有质的突破
多线程按我的理解就是说 在python中所有的代码都是按每行去一行一行执行 如果有一个循环或者是死循环 那么就不能继续执行下面的代码因此启用多线程就可以同时执行循环和循环外的代码
from multiprocessing import Process
#同时打印给的参数
count = 0
def outpu(q,o):
print(os.getpid())
global count
while count < 10:
print(q,o,end='', flush=True)# flush 缓存可以不会发生错误可以同时储存
count += 1
def main():
Process(target=outpu, args=('A',)).start()#args后面跟的是元组如果是字符串要加‘,’
#p = process(target = outpu) 是该表达式的缩写 代码要尽量简洁
#p.start()
Process(target=outpu,args=('B',)).start()
多线程
一个进程通常划分为多个线程(thread) 线程是进程的执行单元
也是操作系统分配CUP的基本单元 多线程更多的获取cpu的调度
在多线程中同时执行某个函数其意义和多进程不同在于 CUP不能同时分配他们同时执行只能说是用最快的速度随机分配他们去执行,而多进程表示分别执行意味着一个去抢一个互不干扰,一个影响另一方数据,一个不影响
用上面例子说明
守护线程 daemon 不值得保护的线程 其他线程如果都执行完了那么守护线程自动结束
from threading import Thread
count = 0
def outpu(q,o):
print(os.getpid())
global count
while count < 10:
print(q,o,end='', flush=True)
count += 1
def main():
# 守护线程 daemon 不值得保护的线程 其他线程如果都执行完了那么守护线程自动结束
# daemon = True ——设置为守护线程
# Thread(target=ouput,args=('A',),daemon=True).start()
# Thread(target=ouput,args=('B',),daemon=True).start()
Thread(target=outpu, args=('A')).start()
Thread(target=outpu,args=('B',)).start()
#打印出来的就是随机的只有10个AB
#上面打出来的就是10个A10个B
创建线程的两种方法
1.直接创建Thread对象并通过 target参数指定线程启动后要执行的任务
2.继承Thread自定义线程 通过重写run方法指定线程启动后执行的任务
#方法2:
class My(Thread):
def __init__(self, name):
super().__init__()
self.name = name
# 钩子函数(hook) / 回调函数(callback)
def run(self):
for _ in range(10000):
print(self.name,end="",flush=True)
def ma():
My('A').start()
My("B").start()
如果在多线程或者进程中加 ‘.jion‘ 表示等待运行完 避免计时出现错误
import time
from threading import Thread
from multiprocessing import Process
def down(q):
print('%s' % q)
time.sleep(3)
print('wanc')
class Down(Process):
def __init__(self,name):
super().__init__()
self.name = name
def run(self):
down(self.name)
def main():
star = time.time()
p1 = Process(target=down,args=('a',))
p1.start()
p2 = Process(target=down,args=('b',))
p2.start()
p3 = Down('c')
p3.start()
# join表示等待运行完 避免计时出现错误 否则会先显示时间就不会死3秒了
p3.join()
p1.join()
p2.join()
end = time.time()
print('yong%f' % (end -star))
if __name__ == '__main__':
main()
锁机制
"""假设100个账户同时往银行里存钱"""
import time
from multiprocessing import Process,Lock
from threading import Thread,Lock
class Account(object):
def __init__(self):
self._balance = 0
self._lock = Lock()
@property
def balance(self):
return self._balance
def deposit(self,money):
# 当多个线程同时访问一个资源的时候就有可能因竞争资源导致状态错误
# 被多个线程访问的资源我们成为临界资源 对临界资源的访问需要加上保护
if money > 0:
self._lock.acquire()
try:
new = self.balance + money
time.sleep(0.01)
self._balance = new
finally:
self._lock.release()
class Addmoney(Thread):
def __init__(self,mone):
super().__init__()
self.mone = mone
def run(self):
self.mone.deposit(1)
def main():
account = Account()
list = []
for _ in range(100):
a = Addmoney(account)
list.append(a)
a.start()
for b in list:
b.join()
print('%d元' % account.balance)
启动服务器
今天的互联网TCP/IP 协议族 UDP只负责传送
建立一个基于TCP协议的套接字对象
因为我们做的是应用级的产品或者服务所以可以利用现有的传输服务来进行数据传输
for sock import sock
def main():
server = socket()
server.bind(('192.168.199.128', 2333)) # 绑定ip地址(网络上主机的身份标识)+端口(用来区分不同服务的扩展)
# 端口对IP地址的扩展 (端口号2**16 -1)端口区分服务
# 通常端口都用1024以后的端口 因为著名端口都有用过的
# 开始监听客户端的连接
server.listen(512) # 监听 用户排队 512是最合理的 最好都是2的次方
print('服务器已经启动')
while True:
#通过accept方法接受客户端的连接
#该方法是个阻塞式方法(如果没有客户端链接那么就让代码停在此处直到客户端链接)
#accept方法返回的是一个元组 元组的第一个值是客户端的对象
#元组的第二个值又是一个元组 其中有客户端的ip和端口
dy = time.asctime()
dy = str(input('对话窗口:'))
clien, addr = server.accept() # 接受连接
print(addr)
clien.send(dy.encode('utf-8')) # 发送对象
如何连接上创建的服务器
while True:
client = socket()
client.connect(('10.7.189.114',2333))#链接服务器
da = client.recv(512)#接受内容
print(da.decode('utf-8'))#用utf-8格式打印出来
在cmd中的一些命令
ipconfig 查看自己的ip
netstat -na监视哪些端口已经运用了
telnet 10.xxxx 远程连接哪个IP
多人聊天室
综合上面所说由于建立服务器每次传输和接受都要被accep阻断 导致只能作用一个ip因此结合多线程可以解决此事
将ip对象导入列表中 然后接受发送到服务器的消息,然后用该消息发送每一个列表中
rom socket import socket
from threading import Thread
def main():
class ClientHandler(Thread):
def __init__(self, claint):
super().__init__()
self._claint = claint
def run(self):
while True:
try:
data = self._claint.recv(1024)
if data.deconde('utf-8') == 'byebye':
clients.remove(self._claint)
self._claint.close()
break
else:
for client in clients:
client.send(data)
except Exception as e:
print(e)
clients.remove(self._claint)
break
server = socket()
# python 命令行参数 —— sys.argv 表示可以不用把ip写死了 随时可以改
server.bind(('10.7.189.114', 2333))
server.listen(512)
clients = []
while True:
clain,ar = server.accept()
print(ar[0],'连接到服务器')
clients.append(clain)
ClientHandler(clain).start()