admin管理员组

文章数量:1599543

python多线程编程有两个模块,分别是_thread模块和threading模块。

现在我们一般都使用threading模块。

一、threading模块多线程编程的基本知识

threading.Thread(target, name=None, args=() ) :该函数的作用是创建子线程(主函数的线程叫主线程,其他的线程都为子线程)。

target表示为线程体(线程本是函数对象)。

name用来决定线程的名字,不输入或输入None,系统会帮你自动分配名字。

args:用于给函数对象传参数,以元组的形式传参-----传一个参数,args=(3,)

对于子线程而言,创建了以后还需要启动。

用Thread类的start()方法来启动。

例:

t1 = threading.Thread(target=thread_test)
t1.start()

threading.current_thread():返回当前线程对象

threading.main_thread(): 返回主线程对象

threading.active_thread():返回当前活动的线程个数

线程对象的属性--常用的只有一个。

name:线程的名字

例:

t_main = threading.main_thread()
print(t_main.name)
主线程名字为MainThread

也就是说,输出为:MainThread

二、threading的condition类基本内容

condition类的一些方法:

acquire():给该线程体(函数对象)上锁,使其他线程不能进入(执行)该线程体---也叫互斥锁

release():给线程体释放锁

wait(setting):使当前线程体释放锁,并使当前线程体处于阻塞状态。等待其他线程唤醒或者超时后继续执行,setting是超时时间

notify(c):唤醒相同条件变量的一个线程,c是条件变量。

notify_all(c):唤醒相同条件变量的所有线程,c是条件变量。

三、使用condition类实现线程间通信

3.1 经典的堆栈算法---用两个不同的子线程分别进行压栈(也叫入栈)和出栈算法

如果栈已满,你继续压栈,该线程就会进入阻塞状态,就唤醒另一个线程进行出栈;出栈后,再唤醒之前的子线程,再压栈。

如果栈为空,也是一样。

还有一点,使用线程的话一般会使用time模块,使用time.sleep()方法来使线程休眠

上代码:

import threading
import time


condition = threading.Condition()


class Stack:
    def __init__(self):
        self.pointer = 0
        self.data = [-1, -1, -1, -1, -1]

    def get_stack_data_len(self):   # 获取栈的长度
        return len(self.data)

    def get_stack_data(self):       # 获取栈内数据
        return self.data

    # 压栈方法
    def push(self, data):
        global condition
        condition.acquire()     # 上锁
        while self.pointer == len(self.data):   # 栈已满
            print('线程1等待中')
            condition.wait()    # 释放锁,并处于阻塞状态

        condition.notify()  # 通知其他线程,唤醒其他线程

        self.data[self.pointer] = data
        print('数据入栈:', data)
        self.pointer += 1       # 指针上移
        condition.release()     # 解锁
        time.sleep(1)

    # 出栈方法
    def pop(self):
        global condition
        condition.acquire()
        while self.pointer == 0:   # 栈已空
            print('线程2等待中')
            condition.wait()
        condition.notify()

        self.pointer -= 1
        data = self.data[self.pointer]
        print('数据出栈:',data)
        self.data[self.pointer] = -1    # 出栈后,应将数据变为-1
        condition.release()
        return data


def menu():
    print('1.入栈')
    print('2.出栈')
    print('3.栈长度')
    print('4.栈内数据')
    print('0.退出')


if __name__ == '__main__':
    menu()
    stack = Stack()
    is_run = True
    while is_run:
        command = input('请输入选项:')
        if command == '1':
            data = int(input('请输入入栈的数据:'))
            t1 = threading.Thread(target=stack.push, args=(data,))
            t1.start()
            time.sleep(1)

        if command == '2':
            t2 = threading.Thread(target=stack.pop)
            t2.start()
            time.sleep(1)

        if command == '3':
            print('栈长度:',stack.get_stack_data_len())

        if command == '4':
            print('栈内数据:', stack.get_stack_data())

        if command == '0':
            is_run = False
            print('退出')





这个可以自己操作,自己观察。所以我改成了选项的模式来展现。

3.2 生产者和消费者

接下来还有一个:生产者和消费者的(相比于栈,略有改动)

import threading
import time


condition = threading.Condition()


class Stack:
    def __init__(self):
        self.pointer = 0
        self.data = [-1, -1, -1, -1, -1]

    # 压栈方法
    def push(self, data):
        global condition
        condition.acquire()     # 上锁
        while self.pointer == len(self.data):   # 栈已满
            print('生产者等待中')
            condition.wait()    # 释放锁,并处于阻塞状态

        condition.notify()  # 通知其他线程,唤醒其他线程

        self.data[self.pointer] = data
        # print('数据入栈:', data)
        self.pointer += 1       # 指针上移
        condition.release()     # 解锁
        time.sleep(1)

    # 出栈方法
    def pop(self):
        global condition
        condition.acquire()
        while self.pointer == 0:   # 栈已空
            print('消费者等待中。。。')
            condition.wait()
        condition.notify()

        self.pointer -= 1
        data = self.data[self.pointer]
        # print('数据出栈:', data)
        self.data[self.pointer] = -1    # 出栈后,应将数据变为-1
        condition.release()
        return data


stack = Stack()


def producer_thread_body():
    global stack
    for i in range(10):     # 产生10个数据
        stack.push(i)   # 将数据压栈(入栈)
        print('生产:{0}'.format(i))
        # 每产生一个数据,线程就睡眠
        time.sleep(1)   # 睡眠1s


def consumer_thread_body():
    global stack

    for i in range(10):
        data = stack.pop()
        print('消费:{0}'.format(data))
        time.sleep(1)


def main():
    producer = threading.Thread(target=producer_thread_body, name='thread-1')
    producer.start()

    consumer = threading.Thread(target=consumer_thread_body, name='thread-2')
    consumer.start()


if __name__ == '__main__':
    main()


也就是消费者要买东西,

如果有就直接消费,

如果没有那就要等生产者生产后,再通知消费者来消费。

当然控制台输出可能有些出入,因为不同的线程同时输出的话会比较混乱。这个只能自己把握。

本文标签: 线程多线程模块通信Python