学python的第二十天

多线程

以下内容来源于《看漫画学Python》这本书,前面十几天好多内容参考过本书内容,写的挺好。

1 线程相关知识

1.1 进程

        一个进程就是一个正在执行的程序,每一个进程都有自己独立的一块内存空间,一组系统资源。在进程概念中,每一个进程的内部数据和状态都是完全独立的

        在Windows操作系统中,一个进程就是一个exe或者dll程序,它们相互独立,相互也可以通信。

1.2 线程

        在一个进程中可以包含多个线程,多个线程共享一块内存空间和一组系统资源。所以,系统在各个线程之间切换时,开销要比进程小得多,线程被称为轻量级进程。

1.3 主线程

        Python程序至少有一个线程,这就是主线程,程序在启动后由Python解释器负责创建主线程,在程序结束后由Python解释器负责停止主线程。

        在多线程中,主线程负责其他线程的启动,挂起,停止等操作。其他线程被称为子线程。

2 线程模块-----------threading

         Python官方提供的threading模块可以进行多线程编程。threading模块提供了多线程编程的高级API,使用起来比较简单。

         在threading模块中提供了线程类Thread,还提供了很多线程相关的函数,常用如下:

active_count():返回当前处于活动状态的线程个数

current_thread():返回当前的Thread对象

main_thread():返回主线程对象。

主线程是Python解释器启动的线程。示例代码如下:

import threading  # 导入threading模块

t = threading.current_thread()  # 获取当前线程对象
print(t.name)  # 输出当前线程的名字
print(threading.active_count())  # 输出当前活动线程的个数

t = threading.main_thread()
print(t.name)  # 输出主线程的名字

输出结果:当前线程和主线程是同一个 

 3 创建子线程

创建一个可执行的子线程需要:线程对象线程体

线程对象:线程对象是threading模块的线程类Thread或Thread子类所创建的对象。

线程体:线程体是子线程要执行的代码,这些代码会被封装到一个函数中。子线程在启动后会执行线程体。

实现线程体主要有以下两种方式:

1,自定义函数实现线程体

2,自定义线程类实现线程体

3.1 自定义函数实现线程体

创建线程Thread对象的构造方法如下:

Thread(target=None, name=None, args=())

target参数指向线程体函数,可以自定义该线程体的函数;通过name参数可以设置线程名,若省略这个参数,则系统会为其分配一个名称;args是为线程体函数提供的参数,是一个元组类型。

示例代码如下:

import threading
import time


def thread_body():  # 定义线程体函数
    t = threading.current_thread()  # 获取当前线程对象
    for n in range(5):  # 执行5次
        print('第{0}次执行线程{1}'.format(n, t.name))
        time.sleep(2)  # 当前线程休眠两秒
    print('线程{0}执行完毕'.format(t.name))


t1 = threading.Thread(target=thread_body)  # 创建线程对象t1
t2 = threading.Thread(target=thread_body, name='MyThready')  # 创建线程对象t2
t1.start()  # 启动线程t1
t2.start()  # 启动线程t2

输出结果:

 3.2 自定义线程类实现线程体

创建一个Thread子类并重写run()方法,run()方法就是线程体函数

示例代码如下:

import threading
import time


class SmallThread(threading.Thread):
    def __init__(self, name=None):
        super().__init__(name=name)

    def run(self):  # 重写run()方法
        t = threading.current_thread()  # 获取当前线程对象
        for n in range(5):  # 执行5次
            print('第{0}次执行线程{1}'.format(n, t.name))
            time.sleep(2)  # 当前线程休眠两秒
        print('线程{0}执行完毕'.format(t.name))


t1 = SmallThread()  # 创建线程对象t1
t2 = SmallThread(name='MyThready')  # 创建线程对象t2
t1.start()  # 启动线程t1
t2.start()  # 启动线程t2

输出结果: 

 

4 线程管理

线程管理包括: 线程创建,线程启动,线程休眠,等待线程结束,和线程停止。

前三个内容前面已涉及,以下主要是等待线程结束,线程停止的内容。

4.1 等待线程结束

       一个线程(假设是主线程)需要等待另一个线程(假设是t1子线程)执行结束后才能继续执行。

 示例代码如下:

import threading
import time

value = []  # 定义一个共享变量,多个线程可以访问该变量


def thread_body():
    print('t1线程开始...')
    for n in range(2):
        print('t1子线程执行...')
        value.append(n)
        time.sleep(2)
    print('t1子线程结束...')


print('主线程开始执行...')
t1 = threading.Thread(target=thread_body)  # 创建线程对象t1
t1.start()  # 启动线程t1
t1.join()  # 等待线程t1结束
print('value = {0}'.format(value))
print('主线程继续执行...')

输出结果:

 若注释掉t1.join()语句,输出结果为:

 4.2 线程停止

        在线程结束时,线程就停止了,业务复杂时,会在线程体执行一个“死循环”。通过判断停止变量实现线程体是否持续执行“死循环”,“死循环”结束则线程体结束,线程也就结束了。

        一般情况下,死循环会执行线程任务,然后休眠,再执行,再休眠,直到循环结束。

示例代码如下:

import threading
import time

# 线程停止变量
isrunning = True


def workthread_body():  # 定义工作线程体函数
    while isrunning:
        print('工作线程正在执行...')
        time.sleep(5)
    print('工作线程结束')


def controlthread_body():  # 定义控制线程体函数
    global isrunning
    while isrunning:
        command = input('请输入停止指令:')
        if command == 'exit':
            isrunning = False
            print('控制线程结束')


workthread = threading.Thread(target=workthread_body)  # 创建工作线程对象
workthread.start()  # 启动工作线程
controlthread = threading.Thread(target=controlthread_body)  # 创建控制线程对象
controlthread.start()  # 启动控制线程

输出结果如下:

 5 爬虫下载图片示例:

import threading
import time
import urllib.request

# 线程停止变量
isrunning = True


def workthread_body():  # 定义工作线程体函数
    while isrunning:
        print('工作线程正在执行...')
        download()  # 调用下载图片的函数
        time.sleep(5)
    print('工作线程结束')


def controlthread_body():  # 定义控制线程体函数
    global isrunning
    while isrunning:
        command = input('请输入停止指令:')
        if command == 'exit':
            isrunning = False
            print('控制线程结束')


def download():    # 定义下载图片的函数
    url = '此处替换图片链接'   # 此处替换图片链接
    req = urllib.request.Request(url)  # 创建请求对象
    with urllib.request.urlopen(req) as response:   # 发起请求
        data = response.read()
        f_name = 'download.png'
        with open(f_name, 'wb') as f:  # 打开文件
            f.write(data)
            print('图片下载成功')


workthread = threading.Thread(target=workthread_body)  # 创建工作线程对象
workthread.start()  # 启动工作线程
controlthread = threading.Thread(target=controlthread_body)  # 创建控制线程对象
controlthread.start()  # 启动控制线程


输出结果:

 

 

 

  • 39
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WBY·~阿崟呢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值