python多线程,多进程,以及之间的区别

222 阅读3分钟

一. 多线程:

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()