我们日常的电脑如果有单核cpu的话,运行四个软件,那么这个cpu会快速的切换任务,让我们以为电脑是运行了四个程序。这也就叫并发:假的多任务。如果你的电脑有4核cpu,运行四个程序,那么就是每个cpu的核运行一个软件,这就叫做并行:真的多任务。我们日常的电脑一般都是并发执行程序的。
一般我们执行程序的时候,一般会先起一个进程,然后进程中会自动启动一个主线程,当我们运用多线程的时候,其实是在主线程下创建了几个子线程,但是注意的是,子线程是不断的切换执行的,所以并不是并行去执行的。而且要注意的是,在CPython中,有一个GIL锁,导致一个进程中在同一个时刻中只能运行一个线程,并不能同时运行多个线程,不过我个人觉得运行多线程的好处就是能够数据共享,多进程的数据都是独立的,数据共享比较困难,但是多进程也有多进程的好处。
线程和进程如何选择:
1、计算密集型需要多进程,例如大量的数据计算。
2、i/o密集型需要多线程,例如下载视频、网络文件读写等。
下面就是单线程和多线程的代码演示:
单线程:
import time
#单线程需要的时间会更长
def sing():
"""正在唱歌"""
for i in range(5):
print("正在唱歌")
time.sleep(1)
def dump():
"""正在跳舞"""
for i in range(5):
print("正在跳舞")
time.sleep(1)
def main():
sing()
dump()
if __name__=="__main__":
main()
多线程:
import time
import threading
#单线程需要的时间会更长
def sing():
"""正在唱歌"""
for i in range(5):
print("正在唱歌")
time.sleep(1)
def dump():
"""正在跳舞"""
for i in range(5):
print("正在跳舞")
time.sleep(1)
def main():
# 设置daemon=True会标记其为守护线程,如果剩下的线程只有守护线程时,整个python程序都会退出
a=threading.Thread(target=sing,daemon=False)
b=threading.Thread(target=dump,daemon=False)
a.start()
b.start()
if __name__=="__main__":
main()
当调用start的时候,线程才会启动。
查看当前运行多少线程
import time
import threading
#单线程需要的时间会更长
def sing():
"""正在唱歌"""
for i in range(5):
print("正在唱歌")
time.sleep(1)
def dump():
"""正在跳舞"""
for i in range(5):
print("正在跳舞")
time.sleep(1)
def main():
# 设置daemon=True会标记其为守护线程,如果剩下的线程只有守护线程时,整个python程序都会退出
a=threading.Thread(target=sing,daemon=False)
b=threading.Thread(target=dump,daemon=False)
a.start()
b.start()
while True:
print(threading.enumerate())
break
if __name__=="__main__":
main()
可以清晰的看到一共用到了三个线程,其中一个主线程和两个子线程 ,注意如果主线程先死了,那么子线程就不会去运行。一般主线程会最后退出,因为主线程可以将子线程的垃圾进行回收。
重写类来调用线程
一般用于比较复杂的函数,才会使用类方法 ,注意:创建一个类就只能调用一个线程
import time
import threading
class MyThread(threading.Thread):#这个类继承的是多线程
def run(self) -> None:
for i in range(5):
print("正在跳舞")
msg=self.name
print("msg",msg)
time.sleep(1)
if __name__ == '__main__':
a=MyThread()
a.start()#a.start()调用的是Thread的方法,它里面会自动调用run方法
import time
import threading
class MyThread(threading.Thread):#这个类继承的是多线程
def run(self) -> None:
for i in range(5):
print("正在跳舞")
msg=self.name
self.sing()
print("msg",msg)
time.sleep(1)
def sing(self):
print("我想要跳舞")
if __name__ == '__main__':
a=MyThread()
a.start()#a.start()调用的是Thread的方法,它里面会自动调用run方法
线程共享全局变量
import threading
import time
num=100
def test1():
global num
num+=1
print("--------test1-------",num)
def test2():
print("--------test2-------",num)
def main():
a = threading.Thread(target=test1, daemon=False)
b=threading.Thread(target=test2,daemon=False)
a.start()
time.sleep(1)
b.start()
if __name__ == '__main__':
main()
多线程传参共享全局变量
import threading
import time
def ptest1(temp):
temp.append(44)
print("--------test1-------",temp)
def ptest2(temp):
print("--------test2-------",temp)
temp_1 = [100, 200]
def main():
a = threading.Thread(target=ptest1, args=(temp_1,))
b=threading.Thread(target=ptest2,args=(temp_1,))
a.start()
time.sleep(1)
b.start()
if __name__ == '__main__':
main()
注意:共享全局变量也有不好的事情,就是线程之间会出现资源竞争的问题。
最后祝大家一起学有所成!