Python:多线程及多进程的使用-Threading and multiprocessing

进程:由程序,数据集,进程控制块三部分组成,它是程序在数据集上的一次运行过程。如果同一段程序在某个数据集上运行了两次,那就是开启了两个进程。进程是资源管理的基本单位。在操作系统中,每个进程有一个地址空间,而且默认就有一个控制进程。
线程:是进程的一个实体,是CPU调度和分派的基本单位,也是最小的执行单位。它的出现降低了上下文切换的消耗,提高了系统的并发性,并克服了一个进程只能干一件事的缺陷。线程由进程来管理,多个线程共享父进程的资源空间。
进程和线程的关系:
一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
资源分配给进程,同一进程的所有线程共享该进程的所有资源。
CPU分给线程,即真正在CPU上运行的是线程。

线程的工作方式:
  如下图所示,串行指线程一个个地在CPU上执行;并行是在多个CPU上运行多个线程;而并发是一种“伪并行”,一个CPU同一时刻只能执行一个任务,把CPU的时间分片,一个线程只占用一个很短的时间片,然后各个线程轮流,由于时间片很短所以在用户看来所有线程都是“同时”的。并发也是大多数单CPU多线程的实际运行方式。

多线程:单核多线程

import threading # 导入threading模块,为多线程非多进程,一个核来跑
from queue import Queue #导入queue模块
import pyhdfs
import pandas as pd
import os
import datetime
import time

prov_id_list = ["010", '011','013'] # 要循环的省份
def runProvDelay(prov_id,queue):
    """主程序"""
    print(f"---------------当前省份为{prov_id}-------------------------")
    # 向队列(共享变量)中写入数据
    queue.put((xxx,xxx))

if __name__ == '__main__':
    start_time = time.time()
    file_time_list_queue = Queue(maxsize=100)  # 用Queue构造一个大小为1000的线程安全的先进先出队列
    # 先创造多个线程
    prov_thread = []
    for prov_id in prov_id_list:
        thread = threading.Thread(target=runProvDelay, args=(prov_id,file_time_list_queue)) # 方法名不可加括号,参数全部写在args中
        prov_thread.append(thread)

    # 启动多个线程,但实际并行度被核的性能限制
    for thread in prov_thread:
        thread.start()
    # 等待所有线程结束,thread.join()函数代表子线程完成之前,其父进程一直处于阻塞状态。
    for thread in prov_thread:
        thread.join()

    prov_time_list = []
    while (file_time_list_queue.empty()==False):
        prov_time = file_time_list_queue.get() #Queue队列的get方法用于从队列中提取元素
        prov_time_list.append(prov_time)

    print(prov_time_list)
    df_file_time_list = pd.DataFrame(file_time_list)
    print("df_file_time_list: %s" % df_file_time_list)

    print("last time: {} s".format(time.time() - start_time)) 

多进程:多核多进程

以并行读取hdfs文件并分析为例

from multiprocessing import Process,Queue # 多进程多个核,Queue用于做共享变量
import pyhdfs
import pandas as pd
import os
import datetime
import time

file_time_list_queue = Queue() # 共享变量,可在各进程间随时写入和读取
fs = pyhdfs.HdfsClient(hosts=['10.162.166.178', '10.162.166.179'], user_name='ubd_oy')
fs.get_active_namenode()  # 返回可用的namenode节点
# fs.get_home_directory()#返回这个用户的根目录
start = datetime.datetime.now()

prov_id_list = ['010', '011', '013'] # 循环的省份

def runProvDelay(prov_id,queue):
    """主程序"""
    print(f"---------------当前省份为{prov_id}-------------------------")
    # 往queue中写入数据
    queue.put((xxx,xxx))

def main(prov_id_list):
      prov_thread = []
    for prov_id in prov_id_list:
        # 将队列传过去,做共享变量使用
        th = Process(target=runProvDelay, args=(prov_id,file_time_list_queue,))
        th.start()
        prov_thread.append(th)
    for thread in prov_thread:
        thread.join()

    # 在主进程中将队列中的数据拿出来放到list里,便于处理
    prov_time_list = []
    while (file_time_list_queue.empty() == False):
        prov_time = file_time_list_queue.get()  # Queue队列的get方法用于从队列中提取元素
        prov_time_list.append(prov_time)

    print(prov_time_list)
    df_file_time_list = pd.DataFrame(prov_time_list)
    # df_file_time_list.rename( columns={0: 'prov_id', 1: 'start_time_min',2:'start_time_max',3:'start_time_avg',4:'insert_time',5:'check_time'},inplace=True)
    df_file_time_list.rename(
        columns={0: 'prov_id', 1: 'start_time_min', 2: 'start_time_max', 3: 'insert_time', 4: 'check_time'},
        inplace=True)

    print("df_file_time_list: %s" % df_file_time_list)
    # end = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    end = datetime.datetime.now()

    print("start: %s" % start)
    print("end: %s" % end)
    print("all_time: %s" % (end - start))

if __name__ == '__main__':
    # 执行
    main(prov_id_list)
posted @ 2020-08-14 09:22  手心里的宇宙  阅读(345)  评论(0编辑  收藏  举报