Python基础

Python多线程

2019-02-23  本文已影响16人  马本不想再等了

1. 理解

多个任务同时进行。
Sublime、Chrome、Pycharm、QQ这四个进程同时开启并运行,CPU高速切换实现多进程。
在QQ这一个进程中可以同时使进行语音、视频、文字的传输,这就是多线程。
再理解。
运行一段代码,系统就开启了一个进程,在代码中需要同时进行多个部分的运行,就需要创建多线程。

2. 创建线程

2.1 面向过程

t = treading.Thread(target=xxx, name=xxx, args=(xx, xx))
target:线程启动之后要执行的函数
name:线程的名字
args:主线程项子线程传递的参数
threading.current_thread().name:获取当前线程的名字
t.start():启动线程
t.join():让主线程等待子线程结束
实例代码如下:

import threading
import time


def sing(a):
    print('线程%s,接收参数%s' % (threading.current_thread().name, a))
    for i in range(1, 4):
        print('我在唱什么')
        time.sleep(1)

def dance(b):
    print('线程%s,接收参数%s' % (threading.current_thread().name, b))
    for i in range(1, 4):
        print('我在跳什么')
        time.sleep(1)

def main():
    a = "彩云之南"
    b = "民族舞"
    # 创建唱歌线程
    tsing = threading.Thread(target=sing, name="唱歌", args=(a,))
    # 创建跳舞线程
    tdance = threading.Thread(target=dance, name='跳舞', args=(b,))
    # 启动线程
    tsing.start()
    tdance.start()
    # 让主线程等待子线程结束之后在结束
    tsing.join()
    tdance.join()
    # 主线程在运行
    print('这是主线程')

if __name__ == '__main__':
    main()

>>>线程唱歌,接收参数彩云之南
>>>我在唱什么
>>>线程跳舞,接收参数民族舞
>>>我在跳什么
>>>我在跳什么
>>>我在唱什么
>>>我在跳什么
>>>我在唱什么
>>>这是主线程

2.2 面向对象

定义一个类,继承自threading.Thread,重写run方法,需要线程名字、传递参数,重写构造方法,在重写构造方法的时候,一定要先手动调用父类的构造方法。
实例代码如下:

import threading
import time


# 写一个类,继承自threading.Thread
class SingThread(threading.Thread):
    def __init__(self, name, a):
        super().__init__()
        self.name = name
        self.a = a

    def run(self):
        print('线程%s,接收参数%s' % (self.name, self.a))
        for i in range(1, 3):
            print('我在唱七里香')
            time.sleep(1)

class DanceThread(threading.Thread):
    def __init__(self, name, b):
        super().__init__()
        self.name = name
        self.b = b

    def run(self):
        print('线程%s,接收参数%s' % (self.name, self.b))
        for i in range(1, 3):
            print('我在跳广场舞')
            time.sleep(1)

def main():
    # 创建线程(实例化)
    tsing = SingThread('sing', '周杰伦的歌')
    tdance = DanceThread('dance', '外面广场的')
    # 启动线程
    tsing.start()
    tdance.start()
    # 让主线程等待结束
    tsing.join()
    tdance.join()
    print('主线程和子线程全部结束')

if __name__ == '__main__':
    main()
>>>线程sing,接收参数周杰伦的歌
>>>我在唱七里香
>>>线程dance,接收参数外面广场的
>>>我在跳广场舞
>>>我在唱七里香
>>>我在跳广场舞
>>>主线程和子线程全部结束

2.3 线程同步

线程之间共享全局变量,很容易发生数据紊乱问题,这个时候要使用线程锁。

# 创建锁
suo = threading.Lock()
# 获取锁
sou.acquire()
# 释放锁
sou.release()

2.4 队列(queue)

以爬虫为例会有下载线程,解析线程等。
q = Queue(5) 创建队列,且最大存储量为5
q.put('xxx') 如果队列满,程序卡在这里等待
q.put('xxx', False) 如果队列满,直接报错
q.put('xxx', Ture,3) 如果队列满,等待3s,后报错
获取数据
q.get() 如果队列空,程序卡在这里等待
q.get(False) 如果队列空,直接报错
q.get(True, 3) 如果队列空,等待三秒,再报错
常用方法
q.empty() 判断队列是否为空
q.full() 判断队列是否已满
q.qsize() 获取队列长度
实例代码如下:

from queue import Queue


# 创建队列
q = Queue(5)
# 存数据
q.put('Python')
q.put('Java')
q.put('Golang')
q.put('C#')
q.put('C++')
# 队列满,直接报错
# q.put('C', False)
# 队列满,等待三秒,再报错
# q.put('C', True, 3)
# 取数据
print(q.get())
print(q.get())
print(q.get())
print(q.get())
print(q.get())
# 队列空,直接报错
# print(q.get(False))
# 队列空,等待三秒,再报错
# print(q.get(True, 3))
上一篇下一篇

猜你喜欢

热点阅读