面向过程创建线程
import threading
import time
def sing(a):
# threading.current_thread().name:创建线程时name的值
print('线程为:{},接收过来的参数为:{}'.format(threading.current_thread().name,a))
for x in range(1, 3):
print('我在唱歌')
time.sleep(1)
def dance(a):
# threading.current_thread().name:创建线程时name的值
print('线程为:{},接收过来的参数为:{}'.format(threading.current_thread().name,a))
for x in range(1, 3):
print('我在跳舞')
time.sleep(1)
def main():
a = '我是线程参数'
# 创建第1个唱歌线程,
# target:该线程运行起来时执行的函数,
# name:给该线程起个名字,
# args:一个元组,用于给线程执行的函数内传递参数
tsing = threading.Thread(target=sing, name='唱歌', args=(a,))
# 创建第2个跳舞线程
tdance = threading.Thread(target=dance, name='跳舞', args=(a,))
# 启动第1个线程
tsing.start()
# 启动第2个线程
tdance.start()
# 让主线程等待指定的子线程结束之后再结束
tsing.join()
tdance.join()
# 主线程在运行
print('我是主线程')
if __name__ == '__main__':
main()
执行结果为:
线程为唱歌,接收过来的参数为我是线程参数
我在唱歌
线程为跳舞,接收过来的参数为我是线程参数
我在跳舞
我在唱歌
我在跳舞
我是主线程
面向对象创建线程
import threading
import time
# 写一个类,继承自threading.Thread
# main
class OneThread(threading.Thread):
# 如果需要接收线程的名字和给线程传递的参数可以写到__init__里
def __init__(self, name, a):
# 因为这里继承自threading.Thread类,需要调用一下父类的__init__方法,
# 否则会出错
super().__init__()
self.name = name
self.a = a
# run方法名字必须为run,下面启动线程时会自动执行run方法
def run(self):
print('线程名字是:{},接收的参数是:{}'.format(self.name, self.a))
for x in range(1, 6):
print('我是线程1')
time.sleep(1)
class TowThread(threading.Thread):
def __init__(self, name, a):
super().__init__()
self.name = name
self.a = a
def run(self):
print('线程名字是:{},接收的参数是:{}'.format(self.name, self.a))
for x in range(1, 6):
print('我是线程2')
time.sleep(1)
def main():
# 启动两个线程
one = OneThread('one', '我是线程1传递的参数')
tow = TowThread('tow', '我是线程2传递的参数')
# 启动两个线程
one.start()
tow.start()
# 让主线程等待子线程结束
one.join()
tow.join()
print('主线程和子线程全部结束')
if __name__ == '__main__':
main()
执行结果为:
线程名字是:one,接收的参数是:我是线程1传递的参数
我是线程1
线程名字是:tow,接收的参数是:我是线程2传递的参数
我是线程2
我是线程1
我是线程2
我是线程2
我是线程1
我是线程2
我是线程1
我是线程1
我是线程2
主线程和子线程全部结束
线程同步
线程之间共享全局变量,但当其中一个线程正在修改一个全局变量时,另一个线程也访问了这个全局变量,那么访问的是第一个线程修改之前的全局变量还是修改之后的全局变量呢?这个时候需要用到线程锁,但还有一个问题,比如现在有3个线程要用到一个全局变量,第一个线程先抢到了这个全局变量,并加了线程锁,那么剩下的两个线程只能等,等第一个线程执行完毕,释放线程锁时再去抢,以此类推,所以线程执行没有顺序.
import threading
# 创建锁
suo = threading.Lock()
# 上锁
suo.acquire()
# 释放锁
suo.release()
队列(生产者消费者)
from queue import Queue
# 创建队列,括号内的数字指定了这个队列内最多放多少个元素,
# 不写的话代表任意个数
q = Queue(5)
# 向队列中添加数据(生产者)
q.put('老王')
q.put('老李')
q.put('老宋')
q.put('老张')
q.put('老杨')
# 当队列中元素已经满了后,再往里面添加数据,程序会阻塞到这里不执行,
# 直到队列中的元素被拿出去后再执行
# q.put('第6个数据')
# 也可以在后面写上一个False,代表队列满了之后再往里添加直接抛出异常
# q.put('第6个数据', False)
# 如果队列满了,程序等待3秒后,队列还是满的才会抛异常
# q.put('第6个数据', True, 3)
# 从队列中取数据(消费者)
print(q.get())
print(q.get())
print(q.get())
print(q.get())
print(q.get())
# 当队列中没数据后再取,程序会阻塞在这里,等待队里中出现新数据后再执行
# print(q.get())
# 也可以添加False,当队里中没数据时再取的话抛异常
# print(q.get(False))
# 当队里内没数据时等待3秒,3秒过后还是没有数据抛异常
# print(q.get(True,3))
# 判断队列是否为空
q.empty()
# 判断队列是否已满
q.full()
# 获取队列长度
q.qsize()
# print(q)