python多线程编程 入门笔记(下)

python多线程编程(下)

前一篇文章链接:python多线程线程(上)


前言

在b站看到的多线程视频,现将笔记分享如下。


一、线程的介绍

1.1 实现多任务的另一种形式

在python中,想要实现多任务还可以使用多线程来完成

1.2 为什么使用多线程

进程是分配资源的最小单位,一旦创建一个进程就会分配一定的资源,就像跟两个人聊QQ就需要打开两个QQ软件一样是比较浪费资源的。
线程是程序执行的最小单位,实际上进程只负责分配资源,而利用这些资源执行程序的是线程。也就是说进程是线程的容器,一个进程中最少有一个线程来负责执行程序。同时线程自己不拥有系统资源,只需要一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。这就像通过一个QQ软件(一个进程)打开两个窗口(两个线程)跟两个人聊天一样,实现多任务的同时也节省了资源

1.3 多线程的作用

同时运行任务A和任务B

1.4 多线程的作用

1.5 总结

实现多任务的另一种形式
线程是程序执行的最小单位
同属一个进程的多个线程共享进程所拥有的全部资源

二、多线程完成多任务

2.1 线程的创建步骤

1 导入线程模块

import threading

2 通过线程类创建线程对象

线程对象 = threading.Thread()

3 启动线程执行任务

线程对象.start()

2.2 通过线程类创建线程对象

线程对象 = threading.Thread(target=任务名)
参数名 说明
target 执行的目标任务名,这里指的是函数名(方法名)
name 线程名,一般不用设置
group 线程组,目前只能使用None

2.3 线程创建与启动的代码

# 创建子线程
sing_thread = threading.Thread(target=sing)
# 创建子线程
dance_thread = threading.Thread(target=dance)
# 启动线程
sing_thread.start()
dance_thread.start()

例子


# 1 导入进程包
import threading
import time

# 唱歌
def sing():
    for i in range(3):
        print("唱歌...")
        time.sleep(1)

# 跳舞
def dance():
    for i in range(3):
        print("跳舞...")
        time.sleep(1)


if __name__ == '__main__':
    start_time = time.time()
    # 创建子线程
    sing_thread = threading.Thread(target=sing)
    # 创建子线程
    dance_thread = threading.Thread(target=dance)
    # 启动线程
    sing_thread.start()
    dance_thread.start()

    print(time.time() - start_time)

三、线程执行带有参数的任务

3.1 线程执行带有参数的任务

参数名 说明
args 以元组的方式给执行任务传参
kwargs 以字典方式给执行任务传参

3.2 args参数的使用

# target: 线程执行的函数名
# args: 表示以元组的方式给函数传参
sing_thread = threading.Thread(target=sing,args=(3,))
# 注意加了,才是元组,表示将3传给函数的参数
sing_thread.start()

3.3 kwargs参数的使用

# target: 线程执行的函数名
# kwargs: 表示以字典的方式给函数传参
dance_thread = threading.Thread(target=dance,kwargs={"count":3} )
# 启动线程
dance_pthread.start()

例子


# 1 导入进程包
import threading
import time

# 唱歌
def sing(num,name):
    for i in range(num):
        print(name,end="唱歌...\n")
        time.sleep(1)

# 跳舞
def dance(count,name):
    for i in range(count):
        print(name,end="跳舞...\n")
        time.sleep(1)


if __name__ == '__main__':
    start_time = time.time()
    # args 以元组方式给执行任务传递参数
    sing_thread = threading.Thread(target=sing,args=(3,"小明"))
    # kwargs 以字典方式给执行任务传递参数
    dance_thread = threading.Thread(target=dance,kwargs={"name":"小红","count":2})
    # 启动线程
    sing_thread.start()
    dance_thread.start()

    print(time.time() - start_time)

注意事项同多进程实现一样

四、主线程和子线程的结束顺序

对比进程
主线程会等待所有的子线程结束后主线程再结束

import time
import threading

def work():
    for i in range(10):
        print("工作...")
        time.sleep(0.2)

if __name__=="__main__":
    sub_thread=threading.Thread(target=work)
    sub_thread.start()

    # 主线程等待1s后结束
    time.sleep(1)
    print("主线程结束了")
#结论 主线程会等待所有子线程结束再结束

4.1 设置守护主线程

要想主线程不等待子线程执行完成,可以设置守护主线程

# 设置守护主线程方式1 daemon=True 守护主线程
work_thread = threading.Thread(target=work,daemon=True)
# 设置守护主线程方式2 
# work_thread.setDaemon(True)
work_thread.start()
# 主线程延迟1s
time.sleep(1)
print("over")

例子

import time
import threading

def work():
    for i in range(10):
        print("工作...")
        time.sleep(0.2)

if __name__=="__main__":
    # sub_thread=threading.Thread(target=work)
    # sub_thread.start()

    # 主线程结束时不想等待子线程结束再结束,可以设置守护子线程
    # 1. threading.Thread(target=work,daemon=True)
    # sub_thread=threading.Thread(target=work,daemon=True)
    # sub_thread.start()

    # 2.
    sub_thread=threading.Thread(target=work)
    sub_thread.setDaemon(True)
    sub_thread.start()

    # 主线程等待1s后结束
    time.sleep(1)
    print("主线程结束了")
#结论 主线程会等待所有子线程结束再结束

五、线程间的执行顺序

5.1 线程之间执行是无序的

for i in range(5):
	sub_thread=threading.Thread(target=task)
	sub_thread.start()

5.2 获取当前线程信息

# 通过current_thread()方法获取线程对象
current_thread = threading.current_thread()
# 通过current_thread对象可以知道线程的相关信息,例如被创建的顺序
print(current_thread)

例子

import threading
import time
def task():
    time.sleep(1)
    # 获取当前线程的线程对象
    current_thread=threading.current_thread()
    print(current_thread)


if __name__=="__main__":
    for i in range(5):
        sub_thread=threading.Thread(target=task)
        sub_thread.start()

# 多线程的执行时无序的,由cpu调度

六、进程和线程对比

6.1 关系对比

1 线程是依附在进程里面的,没有进程就没有线程
2 一个进程默认提供一条线程,进程可以创建多个线程

6.2 区别对比

1 创建进程的资源开销要比创建线程的资源开销要大
2进程是操作系统资源分配的基本单位,线程是CPU调度的基本单位
3 线程不能够独立执行,必须依存在进程中

6.3 优缺点对比

1进程优缺点:
优点:可以用多核
缺点:资源开销大
2线程优缺点:
优点:资源开销小
缺点:不可用多核

七、案例 多进程实现视频文件夹高并发copy器

需求分析

1.目标文件夹是否存在,如果不存在就创建,如果存在则不创建
2.遍历源文件夹中所有文件,并拷贝到目标文件夹
3.采用进程实现多任务,完成高并发拷贝

实现步骤

1.定义源文件夹所在的路径,目标文件夹所在路径

# 1 定义源文件夹所在的路径,目标文件夹所在路径
source_dir = "python教学视频"
dest_dir="/home/python/桌面/test"

2.创建目标文件夹

try:
	# 2 创建目标文件夹
	os.mkdir(dest_dir)
except:
	print("目标文件夹已经存在,未创建~")

3.通过os.listdir获取源目录中的文件列表

# 3 通过os.listdir获取源目录中的文件列表
file_list=os.listdir(source_dir)
print(file_list)

4.遍历每个文件,定义一个函数,专门实现文件拷贝

# 4 遍历每个文件,定义一个函数,专门实现文件拷贝
for file_name in file_list:
	copy_work(file_name,source_dir, dest_dir)

5.采用线程实现多任务,完成高并发拷贝

# 4 for循环依次拷贝每个文件
for file_name in file_list:
	# copy_work(file_name,source_dir, dest_dir)
	sub_thread= threading.Thread(target=copy_work,args=(file_name,source_dir, dest_dir))
	sub_thread.start()

实现

import os
import threading


def copy_file(file_name, source_dir, dest_dir):
    # 1 拼接源文件路径和目标文件路径
    source_path = source_dir + '\\' + file_name
    dest_path = dest_dir + '\\' + file_name
    # 2 打开源文件和目标文件
    with open(source_path, 'rb') as source_file:
        with open(dest_path, 'wb') as dest_file:
            # 3 循环读取源文件到目标路径
            while True:
                data = source_file.read(1024)
                if data:
                    dest_file.write(data)
                else:
                    break


if __name__ == '__main__':
    # 1 定义源文件夹和目标文件夹
    source_dir = "源文件夹"
    dest_dir = "目标文件夹2"

    # 2.创建目标文件夹
    try:
        os.mkdir(dest_dir)
    except:
        print("目标文件夹已经存在")

    # 3.读取源文件夹的文件列表
    file_list = os.listdir(source_dir)

    # 4.遍历文件列表实现拷贝
    for file_name in file_list:
        # copy_file(file_name, source_dir, dest_dir)
        # 5.使用多线程实现多任务拷贝
        sub_thread = threading.Thread(target=copy_file, args=(file_name, source_dir, dest_dir))
        sub_thread.start()

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值