Python多线程
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))