思路渐进目录:
- 1、单任务
- 2、多线程的创建
- 3、主线程主动等待子线程退出之后执行代码
- 4、创建线程的第二种方式_验证线程的执行顺序
- 5、多线程共享全局变量
- 6、给线程函数代码传递参数
- 7、多任务的聊天工具
1、单任务
from time import sleep
def sing():
for i in range(3):
print("正在唱歌...%d"%i)
sleep(1)
def dance():
for i in range(3):
print("正在跳舞...%d"%i)
sleep(1)
if __name__ == '__main__':
sing() #唱歌
dance() #跳舞
2、多线程的创建
import time
import threading
def saySorry():
print("亲爱的,我错了,我能吃饭了吗?")
print(threading.enumerate())
time.sleep(1)
if __name__ == '__main__':
for i in range(5):
# saySorry()
# 创建一个线程
# 创建一个线程执行的计划 target指定线程在执行时 执行的函数
thd = threading.Thread(target=saySorry)
# 启动计划 -- 创建并且执行子线程
thd.start()
# 查看当前进程内部存活的所有的线程列表 《主线程 子线程》 ----> len(列表) 线程数量
# [<_MainThread(MainThread, started 139901408708352)>,
# <Thread(Thread-1, started 139901382989568)>,
# <Thread(Thread-2, started 139901374596864)>,
# <Thread(Thread-4, started 139901357811456)>,
# <Thread(Thread-5, started 139901349418752)>,
# <Thread(Thread-3, started 139901366204160)>]
# print(threading.enumerate())
# while True:
# if len(threading.enumerate()) == 1:
# print("所有的子线程都退出了")
# break
# else:
# time.sleep(1)
# 默认情况下 主线程会等待所有的子线程退出之后再退出
3、主线程主动等待子线程退出之后执行代码
from time import sleep
import threading
def sing():
for i in range(3):
print("正在唱歌...%d"%i)
def dance():
for i in range(3):
print("正在跳舞...%d"%i)
sleep(1)
if __name__ == '__main__':
sing_thd = threading.Thread(target=sing)
sing_thd.start()
dance_thd = threading.Thread(target=dance)
dance_thd.start()
# while True:
# if len(threading.enumerate()) == 1:
# print("所有的子线程都退出了")
# break
# else:
# sleep(1)
# 在主线程阻塞等待 Thread对象标识的子线程退出之后 才会继续往下执行代码
sing_thd.join()
dance_thd.join()
print("太棒了")
- 4、创建线程的第二种方式_验证线程的执行顺序
import threading
import time
class myThread(threading.Thread):
"""1 集成Thread 2 实现其中run方法 3 创建该类的实例对象 4对象.start()启动创建和执行"""
def run(self):
for i in range(3):
time.sleep(1)
msg = "I'm " + self.name + ' @ ' + str(i) # name属性中保存的是当前线程的名字
print(msg)
if __name__ == '__main__':
for i in range(5):
mt = myThread()
mt.start() # 创建子线程 在子线程中调用run方法
# 多个线程执行的时候 顺序是随机 无序的
# while True:
# time.sleep(1)
# print("主线程正在执行")
5、多线程共享全局变量
import threading
import time
g_number = 0
# 创建一把全局互斥锁
g_lock = threading.Lock()
def worker1():
global g_number
for i in range(1000000):
# 尝试获取并且加锁 如果没有被锁定 就可以被我锁定;
# 如果已经被锁定 阻塞等待 直到成功获取并且锁定
g_lock.acquire()
g_number += 1
# 释放锁资源 解锁 未锁定 ----> 未锁定状态
g_lock.release()
# print(g_number)
def worker2():
global g_number
for i in range(1000000):
g_lock.acquire()
g_number += 1
g_lock.release()
# time.sleep(1)
if __name__ == '__main__':
thd1 = threading.Thread(target=worker1)
thd1.start()
thd2 = threading.Thread(target=worker2)
thd2.start()
thd1.join()
thd2.join()
print("比赛的结果是%d" % g_number)
# 多个线程同时修改同一个数据 会引起异常
6、给线程函数代码传递参数
import threading
import time
g_number = 0
def worker1(lock):
global g_number
for i in range(1000000):
# 尝试获取并且加锁 如果没有被锁定 就可以被我锁定;
# 如果已经被锁定 阻塞等待 直到成功获取并且锁定
lock.acquire()
g_number += 1
# 释放锁资源 解锁 未锁定 ----> 未锁定状态
lock.release()
# print(g_number)
def worker2(lock):
global g_number
for i in range(1000000):
lock.acquire()
g_number += 1
lock.release()
# time.sleep(1)
if __name__ == '__main__':
# 创建一把全局互斥锁
lock = threading.Lock()
# target指定线程在执行时 的函数
# args指定这个函数在执行时 所需的参数构成元组 一个元素的元祖需要在元素后加上,
thd1 = threading.Thread(target=worker1, args=(lock,))
thd1.start()
thd2 = threading.Thread(target=worker2, args=(lock,))
thd2.start()
thd1.join()
thd2.join()
print("比赛的结果是%d" % g_number)
# 多个线程同时修改同一个数据 会引起异常
7、多任务的聊天工具
import socket
import threading
# 主线程 专门以 接收屏幕输入 ----> 发送 --退出
# 创建一个子线程 专门用来收数据
def send_msg(udp_socket):
"""发送一次数据"""
data = input("请输入你想说的话:")
IP = input('请输入你想要聊天的IP地址:')
port = int(input("请输入对方使用的端口:"))
udp_socket.sendto(data.encode(), (IP, port))
def recv_msg(udp_socket):
"""循环接收数据"""
while True:
data, remote_address = udp_socket.recvfrom(4096)
print("接收到来自%s 的数据:%s" % (str(remote_address), data.decode()))
def main():
# 创建UDP套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定端口
udp_socket.bind(('', 9999))
# 创建一个子线程收数据
recv_thd = threading.Thread(target=recv_msg, args=(udp_socket,))
recv_thd.start()
while True:
op = input("请输入你要进行的操作: 1 发送数据 2接收数据 3退出")
if op == '1':
send_msg(udp_socket)
# elif op == '2':
# recv_msg(udp_socket)
elif op == '3':
break
else:
print("你输入有误")
# 关掉套接字
udp_socket.close()
if __name__ == '__main__':
main()