高级编程技巧 学习笔记
一、多任务
有很多的场景中的事情是同时进行的,比如开车的时候 手和脚共同来驾驶汽车,又比如唱歌跳舞也是同时进行的,再比如边敲代码边听歌。
1.1、多任务的理解
- 并行: 真的多任务,cpu 大于当前执行的任务
- 并发: 假的多任务,cpu 小于当前执行的任务
1.2、程序中模拟多任务
import time
import threading
def sing():
for i in range(3):
print("正在唱歌....%d" % i)
time.sleep(1)
def dance():
for i in range(3):
print("正在跳舞....%d" % i)
time.sleep(1)
if __name__ == '__main__':
# sing() # 取消注释对比执行结果
# dance()
t1 = threading.Thread(target=sing) # 子线程
t2 = threading.Thread(target=dance) # 子线程
t1.start()
t2.start()
二、线程
2.1、线程完成多任务
- 主线程会等到子线程执行结果之后, 主线程才会结束
-
setDaemon(True) :守护进程,不等子线程结束,主线程继续执行。
-
join() :等待子线程执行结束,主线程继续执行。
import threading
import time
def demo1():
for i in range(3):
print('demo1')
def demo():
for i in range(5):
print("hello world")
time.sleep(1)
t1 = threading.Thread(target=demo1)
t1.start()
t1.join()
if __name__ == '__main__':
t = threading.Thread(target=demo)
# 守护线程: 不等子线程结束, 主线程继续执行
# t.setDaemon(True)
t.start()
# 等待子线程执行结束, 主线程继续执行
t.join()
print('\nend')
2.2、查看线程数量
threading.enumerate()
查看当前线程的数量
import threading
import time
def demo1():
for i in range(5):
print("--test1--%d" % i)
def demo2():
for i in range(5):
print("--test2--%d" % i)
def main():
t1 = threading.Thread(target=demo1)
t2 = threading.Thread(target=demo2)
t1.start()
t2.start()
print(threading.enumerate())
# [<_MainThread(MainThread, started 13708)>, <Thread(Thread-1, started 6348)>, <Thread(Thread-2, started 14484)>]
# 一个主线程, 两个子线程
if __name__ == '__main__':
main()
多次执行上面代码会发现,打印的线程数量个数会发送改变。
这是因为线程的执行顺序是不固定的,所以可以使用 sleep()
延迟更好的进行观察。
import threading
import time
def demo1():
for i in range(5):
print("--test1--%d" % i)
time.sleep(1)
def demo2():
for i in range(5):
print("--test2--%d" % i)
time.sleep(1)
def main():
t1 = threading.Thread(target=demo1)
t2 = threading.Thread(target=demo2)
t1.start()
t2.start()
print(threading.enumerate())
# # 获取当前程序所有的线程
# # 线程运行是没有先后顺序的
# # 可以打印线程数量方便观察
# while True:
# print(threading.enumerate())
# if len(threading.enumerate()) <= 1:
# break
# time.sleep(1)
if __name__ == '__main__':
main()
2.3、子线程的执行与创建
-
当调用 Thread 的时候,不会创建线程。
-
当调用 Thread 创建出来的实例对象的 start 方法的时候,才会创建线程,并且开始运行这个线程。
三、继承 thread 类创建线程
-
类中一定要有
run()
方法 -
进程创建依然是
start()
class A(threading.Thread):
def run(self):
for i in range(5):
print(i)
if __name__ == '__main__':
t = A()
t.start()
四、多线程共享全局变量(线程间通信)
import threading
import time
def demo1():
global num
num += 1
print("demo1 --- %d" % num)
def demo2():
print("demo2 --- %d" % num)
def main():
t1 = threading.Thread(target=demo1)
t2 = threading.Thread(target=demo2)
t1.start()
time.sleep(1) # 不使用 sleep 有可能会先运行 t2 子线程, 则打印出来 num=100
t2.start()
time.sleep(1)
print("main --- %d" % num)
if __name__ == '__main__':
num = 100
main()
五、多线程传参
threading.Thread()
添加一个 args 参数
import threading
import time
def demo1(num):
num.append(33)
print(f"demo1 --- {num}")
def demo2(num):
print(f"demo2 --- {num}")
def main():
t1 = threading.Thread(target=demo1, args=(num, )) # args 需传入元组
t2 = threading.Thread(target=demo2, args=(num, ))
t1.start()
time.sleep(1)
t2.start()
time.sleep(1)
print("main --- %s" % str(num))
if __name__ == '__main__':
num = [11, 22]
main()