一. 多线程:
1.创建一个多线程:
方法一: 使用threading 模块
#coding=utf-8
import threading
import time
def sing():
for i in range(5):
print("singing now")
#如果创建的线程调用的函数结束了,线程就结束了
def dance():
for i in range(5):
print("dancing now")
def main():
t1 = threading.Thread(target=sing) #子线程的创建对象 不会创建出线程 执行start才会产生线程
t2 = threading.Thread(target=dance)
t1.start() #子线程的开始
t2.start()
#线程执行顺序是不确定的
while True:
print(threading.enumerate()) #查看当前的线程数
if len(threading.enumerate()) == 1:
break
time.sleep(1)
if __name__ == '__main__':
main()
方法二: 继承Thread类
#coding= utf-8
import threading
import time
class MyThread(threading.Thread):
def run(self):
for i in range(5):
time.sleep(1)
print("do somthing....lalala")
self.sing()
time.sleep(1)
self.dance()
def sing(self):
for i in range(5):
print("singing.....")
def dance(self):
for i in range(5):
print("danceing.....")
if __name__ == '__main__':
t = MyThread()
t.start()
多线程共享全局变量,会产生资源竞争,所以使用同步方法解决,包括互斥锁,
#coding=utf-8
import threading
import time
g_num = 0
def test1(nums):
global g_num
mutex.acquire()
for i in range(nums):
g_num += 1
mutex.release()
print("test1 num is %d" % g_num)
def test2(nums):
global g_num
mutex.acquire()
for i in range(nums):
g_num += 1
mutex.release()
print("test2 num is %d" % g_num)
mutex = threading.Lock()
def main():
t1 = threading.Thread(target=test1,args=(10000,))
t2 = threading.Thread(target=test2,args=(10000,))
t1.start()
t2.start()
if __name__ == '__main__':
main()
互斥锁在多个锁的情况下会产生死锁,解决办法是: 1.添加超时时间, 2.银行家算法(设计代码时避免死锁)
实例:多线程udp socket编程:
#coding = utf-8
import socket
import threading
def recv_msg(s):
#接收数据
recv_data = s.recvfrom(1024)
print(recv_data)
def send_msg(s,send_data,dest_ip,dest_port):
#发送数据
s.sendto(send_data.encode('utf-8'), (dest_ip, int(dest_port)))
def main():
#1.创建套接字
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
#2.绑定端口
s.bind(("",7080))
#3.接收数据
t_recv = threading.Thread(target=recv_msg,args= (s,))
#4.发送数据
send_data = input("请输入要发送的数据:")
dest_ip = input("请输入对方的ip:")
dest_port = int(input("请输入对方的端口:").strip())
t_send = threading.Thread(target=send_msg,args= (s,send_data,str(dest_ip),dest_port))
t_recv.start()
t_send.start()
if __name__ == '__main__':
main()
二 多进程
1.创建多进程:
方法一:multiprocessing模块
#coding= utf-8
import multiprocessing
def test1():
while True:
print("1111")
def test2():
while True:
print("2222")
def main():
p1 = multiprocessing.Process(target= test1)
p2 = multiprocessing.Process(target= test2)
p1.start()
p2.start()
if __name__ == '__main__':
main()
进程和线程的区别:
进程是资源分配的最小单位, 线程时资源调度的最小单位, 线程必须依赖进程中存在,不可以独立存在,线程间共享内存资源,进程独立的资源; 进程浪费资源,使用线程的情况多一些,
进程间的通信:
1.队列 queue
#coding= utf-8
import multiprocessing
def download_from_web(q):
'''下载数据放入队列'''
data = [11,22,33,44]
for i in data:
q.put(i)
print("下载完成")
def anlize_data(q):
'''解析下载结果'''
waitting = list()
while True:
if q.empty():
break
r = q.get()
waitting.append(r)
print(waitting)
def main():
q = multiprocessing.Queue()
p1 = multiprocessing.Process(target=download_from_web,args=(q,))
p2 = multiprocessing.Process(target=anlize_data,args=(q,))
p1.start()
p2.start()
if __name__ == '__main__':
main()
三. 进程池
当需要创建的进程数量过多时,需要使用multiprocessing的pool模块,
1.进程池创建
#coding= utf-8
from multiprocessing import Pool
import time
import os,random
def worker(msg):
t_start = time.time()
print("%s开始执行,执行的进程id是%d"%(msg,os.getpid()))
time.sleep(random.random()*2)
t_end = time.time()
print("%s执行完毕,耗时%s"%(msg,(t_end-t_start)))
def main():
p = Pool(3)
for i in range(10):
p.apply_async(worker,(i,))
print("-------start------")
p.close()
p.join()
print("------end-------")
if __name__ == '__main__':
main()
案例:
实现多进程拷贝文件:
#coding=utf-8
'''
流程:
1.创建文件夹
2.获取要复制的文件夹的名字
3.打开文件夹下的文件
4.写入到1创建文件夹下面
'''
from multiprocessing import Pool,Manager
import os
def copy_file(q,file_name,old_floder_name,new_floder_name):
'''完成文件的复制'''
#print("模拟拷贝文件%s: 从%s到------>%s"%(file_name,old_floder_name,new_floder_name))
with open(os.path.join(old_floder_name,file_name),'rb') as f_old:
content = f_old.read()
with open(os.path.join(new_floder_name,file_name),'wb') as f_new:
f_new.write(content)
#如果拷贝完对象就向队列中写入消息表示完成了
q.put(file_name)
def main():
#1.获取用户要拷贝的文件夹的名字
old_floder_name = input("请输入原文件夹的名字:")
#2.创建一个新的文件夹 os.mkdir()
try:
new_floder_name = old_floder_name + '[复件]'
os.mkdir(new_floder_name)
except:
pass
#3.获取文件夹中所有待拷贝的文件 os.listdir()
file_names = os.listdir(old_floder_name)
#创建进程池
p = Pool(5)
# 创建queue
q = Manager().Queue()
#向进程池中添加拷贝文件的任务
for file_name in file_names:
p.apply_async(copy_file,args=(q,file_name,old_floder_name,new_floder_name))
p.close()
#p.join()
all_file = len(file_names)
file_count = 0
#显示进度条的功能
while True:
file = q.get()
file_count += 1
print("\r拷贝进度:%.2f%%" % (file_count *100/ all_file),end = '')
if file_count >= all_file:
break
if __name__ == '__main__':
main()