栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

python笔记 - 多线程(十八)

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

python笔记 - 多线程(十八)

线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制
每个线程都有一组 CPU 寄存器,称为线程的上下文,该上下文反映了线程上次运行该线程的 CPU 寄存器的状态
什么是多线程

线程可以分为:

  • 内核线程:由操作系统内核创建和撤销。
  • 用户线程:不需要内核支持而在用户程序中实现的线程
线程创建方式 1、函数式

调用_thread模块中的start_new_thread()函数产生新线程
为了兼容性,Python3 将 thread 重命名为 “_thread”
不推荐

导入:import _thread

_thread.start_new_thread(function, args[, kwargs])
  • function:线程函数。
  • args:传递给线程函数的参数,必须是tuple类型。
import _thread
import time


def print_time(threadName, delay):
    count = 0
    while count < 6:
        time.sleep(delay)
        count += 1
        print(f"{threadName}:{time.ctime(time.time())}")

try:
    _thread.start_new_thread(print_time, ("线程一", 2))
    _thread.start_new_thread(print_time, ("线程二", 4))
except:
    print('无法启动线程')

while 1:
    pass

结果:

线程一:Thu Jul 21 12:07:48 2022
线程二:Thu Jul 21 12:07:50 2022
线程一:Thu Jul 21 12:07:50 2022
线程一:Thu Jul 21 12:07:52 2022
线程二:Thu Jul 21 12:07:54 2022
线程一:Thu Jul 21 12:07:54 2022
线程一:Thu Jul 21 12:07:56 2022
线程二:Thu Jul 21 12:07:58 2022
线程一:Thu Jul 21 12:07:58 2022
线程二:Thu Jul 21 12:08:02 2022
...
2、通过threading创建Thread类,自定义类继承Thread类

threading模块包含了_thread模块中所有方法

导入: import threading
除了_thread模块中的方法,还提供其他方法:

  • threading.currentThread() 返回当前线程变量
  • threading.enumerate() 返回正在运行的线程list
  • threading.activeCount() 返回正在运行的线程数量

Thread类:Thread(target=方法名[, args=(参数1,参数2,...)])

  • target 指要执行的任务,通常是方法名
  • args 指执行任务需要传入的参数,元组形式

Thread类中方法:

  • run() 表示线程活动方法
  • start() 启动线程
  • join([time]) 等待至线程中止
  • isAlive() 返回线程是否活动
  • getName() 返回线程名
  • setName() 设置线程名

使用 threading 模块创建线程

通过直接从 threading.Thread 继承创建一个新的子类,并实例化后调用 start() 方法启动新线程,即它调用了线程的 run() 方法

import threading
import time

# 继承Thread类
class MyThread(threading.Thread):
    def __init__(self, name, delay):
        threading.Thread.__init__(self)
        self.name = name
        self.delay = delay

    def run(self):
        print('开始线程:', self.name)
        print_time(self.name, self.delay, 5)
        print('结束线程:', self.name)


def print_time(threadName, delay, counter):
    while counter:
        time.sleep(delay)
        print(f"{threadName}:{time.ctime(time.time())}")
        counter -= 1

# 创建线程
thread1 = MyThread("线程一", 1)
thread2 = MyThread("线程二", 2)
# 开启线程
thread1.start()
thread2.start()
thread1.join()
thread2.join()

print('退出线程')

结果:

开始线程: 线程一
开始线程: 线程二
线程一:Thu Jul 21 12:06:24 2022
线程二:Thu Jul 21 12:06:25 2022
线程一:Thu Jul 21 12:06:25 2022
线程一:Thu Jul 21 12:06:26 2022
线程二:Thu Jul 21 12:06:27 2022
线程一:Thu Jul 21 12:06:27 2022
线程一:Thu Jul 21 12:06:28 2022
结束线程: 线程一
线程二:Thu Jul 21 12:06:29 2022
线程二:Thu Jul 21 12:06:31 2022
线程二:Thu Jul 21 12:06:33 2022
结束线程: 线程二
退出线程
线程同步

多线程的优势在于可以同时运行多个任务。但是当线程需要共享数据时,可能存在数据不同步的问题
解决资源共享问题,加入锁

锁有两种状态:锁定和未锁定

  • 某个线程操作共享数据时必须先获得锁,其他线程必须等待上一个线程释放锁后,否则同步阻塞

使用threading模块的Lock和Rlock可实现简单线程同步,这两个对象都有acquire方法和release方法,共享数据的操作放在两个方法之间处理

import threading
import time


# 线程类
class MyThread(threading.Thread):
    def __init__(self, name, delay):
        threading.Thread.__init__(self)
        self.name = name
        self.delay = delay

    def run(self):
        print("start thread:", self.name)
        # 获取锁
        threadLock.acquire()
        print_time(self.name, self.delay, 5)
        # 释放锁
        threadLock.release()
        print("end thread:", self.name)


def print_time(threadName, delay, counter):
    while counter:
        time.sleep(delay)
        print(f"{threadName}: {time.ctime(time.time())}")
        counter -= 1


# 线程锁对象
threadLock = threading.Lock()

# 创建线程
thread1 = MyThread('thread-1', 1)
thread2 = MyThread('thread-2', 2)
# 开启线程
thread1.start()
thread2.start()

thread1.join()
thread2.join()

print('退出主线程')

结果:

start thread: thread-1
start thread: thread-2
thread-1: Thu Jul 21 14:58:37 2022
thread-1: Thu Jul 21 14:58:38 2022
thread-1: Thu Jul 21 14:58:39 2022
thread-1: Thu Jul 21 14:58:40 2022
thread-1: Thu Jul 21 14:58:41 2022
end thread: thread-1
thread-2: Thu Jul 21 14:58:43 2022
thread-2: Thu Jul 21 14:58:45 2022
thread-2: Thu Jul 21 14:58:47 2022
thread-2: Thu Jul 21 14:58:49 2022
thread-2: Thu Jul 21 14:58:51 2022
end thread: thread-2
退出主线程
Queue

Queue 模块中提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列 PriorityQueue

常用方法:

方法描述
qsize()返回队列的大小
empty()是否为空
full()是否满对列
get([block[, timeout]])获取队列,timeout为等待时间
get_nowait()相当于queue.get(False)
put(item)写入队列,timeout为等待时间
put_nowait()相当于queue.put(item, False)
task_done()完成任务后向完成的队列发送信号
join()等待队列为空时,执行其他操作
import queue
import threading
import time


# 线程类
class MyThread(threading.Thread):
    def __init__(self, name):
        threading.Thread.__init__(self)
        self.name = name

    def run(self):
        print("start thread:", self.name)
        process_data(self.name)
        print("end thread:", self.name)


exit = 0


def process_data(threadName):
    while not exit:
        # 获取锁
        queueLock.acquire()
        if not workQueue.empty():
            data = workQueue.get()
            queueLock.release()
            print(f"{threadName} 获取 {data}")
        else:
            queueLock.release()
        time.sleep(1)


# 线程锁对象
queueLock = threading.Lock()
# 构建大小为10的队列
workQueue = queue.Queue(10)

# 创建线程
thread1 = MyThread('thread-1')
thread2 = MyThread('thread-2')
# 开启线程
thread1.start()
thread2.start()

# 填充队列
queueLock.acquire()
for i in range(1, 6):
    print(f'填充队列item{i}')
    workQueue.put(f"队列item{i}")
queueLock.release()

# 等待队列清空
while not workQueue.empty():
    pass

exit = 1

# 等待线程完成
thread1.join()
thread2.join()

print('退出主线程')

结果:

start thread: thread-1
start thread: thread-2
填充队列item1
填充队列item2
填充队列item3
填充队列item4
填充队列item5
thread-1 获取 队列item1
thread-2 获取 队列item2
thread-2 获取 队列item3
thread-1 获取 队列item4
thread-1 获取 队列item5
end thread: thread-1
end thread: thread-2
退出主线程
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1022438.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号