Python多线程编程

114 阅读5分钟

并发概念

并发在现实生活中也存在,比如我们去超市的时候,超市只有一个收银台,购买用户非常多的时候,就需要排很长的队,对购买者的购物体验很不好,为了解决这个问题,我们可以开多个窗口多个收银台来减少队伍的长度

在计算机中也会面临这样的问题,每次我们运行一个Python程序,这个程序运行的状态称为进程,比如微信每次运行一次就会产生新的进程,如果想要让程序像超市收银一样能够并发的解决问题,我们需要再进程中引入粒度更小的概念:线程

比如我们在微信中既和一个人语音聊天,又和另一个人文字聊天,这时就需要微信并发的解决问题,就可以使用多线程来完成

多线程编程

这是没有多线程的方式,Python会从for循环的位置开始运行,然后依次调用myThread函数

def myThread(arg1, arg2):
    print("%s %s" % (arg1, arg2))


for i in range(1, 6, 1):
    t1 = myThread(i, i + 1)

'''
1 2
2 3
3 4
4 5
5 6
'''

这是引入多线程的方式,现在我们看不出来单线程和多线程的效果区别

import threading

"""
在Python2.x的版本中,线程的函数库是很多的,有threading,thread 
Python3中thread就变成了_thread,表明这个库已经在Python3中逐步被取代了
"""

def myThread(arg1, arg2):
    print("%s %s" % (arg1, arg2))

for i in range(1, 6, 1):
    t1 = threading.Thread(target=myThread, args=(i, i + 1))
    t1.start()
'''
1 2
2 3
3 4
4 5
5 6
'''

我们引入sleep的方法,让程序暂停一段时间这时程序执行完,打印值,等了一会才结束

import threading
import time


def myThread(arg1, arg2):
    print("%s %s" % (arg1, arg2))
    time.sleep(1)

for i in range(1, 6, 1):
    t1 = threading.Thread(target=myThread, args=(i, i + 1))
    t1.start()
'''
1 2
2 3
3 4
4 5
5 6
'''

但效果还是不明显,我们可以在启动和结束的时候增加新的注释,current_thread,将当前线程运行的状态进行显示

import threading
import time
from threading import current_thread


def myThread(arg1, arg2):
    # 打印线程的开始,线程的结束
    print(current_thread().getName(),'start')
    print("%s %s" % (arg1, arg2))
    time.sleep(1)
    print(current_thread().getName(),'stop')

for i in range(1, 6, 1):
    t1 = threading.Thread(target=myThread, args=(i, i + 1))
    t1.start()

#当主程序完成之后,也打印下看看执行顺序
print(current_thread().getName(),'end')

'''
Thread-2 (myThread) start
2 3
Thread-3 (myThread) start
3 4
Thread-4 (myThread) start
4 5
Thread-5 (myThread) start
5 6
c:\Users\Leon zhao\Desktop\demo.py:8: DeprecationWarning: getName() is deprecated, get the name attribute instead
  print(current_thread().getName(),'start')
Thread-1 (myThread) start
1 2
c:\Users\Leon zhao\Desktop\demo.py:18: DeprecationWarning: getName() is deprecated, get the name attribute instead
  print(current_thread().getName(),'end')
MainThread end
c:\Users\Leon zhao\Desktop\demo.py:11: DeprecationWarning: getName() is deprecated, get the name attribute instead
  print(current_thread().getName(),'stop')
Thread-4 (myThread) stop
Thread-2 (myThread) stop
Thread-5 (myThread) stop
Thread-3 (myThread) stop
Thread-1 (myThread) stop
'''

这个警告表明getName()。这个方法用于获取线程的名称,但现在已经不推荐使用了,应该使用 name 属性来替代 getName() 方法

Thread-2 (myThread) startThread-2import threading
import time
from threading import current_thread


def myThread(arg1, arg2):
    # 打印线程的开始,线程的结束
    print(current_thread().name,'start')
    print("%s %s" % (arg1, arg2))
    # time.sleep(1)
    print(current_thread().name,'stop')

for i in range(1, 6, 1):
    t1 = threading.Thread(target=myThread, args=(i, i + 1))
    t1.start()

#当主程序完成之后,也打印下看看执行顺序
print(current_thread().name,'end')
'''
Thread-1 (myThread) start
1 2
Thread-2 (myThread) start
2 3
Thread-3 (myThread) start
3 4
Thread-4 (myThread) start
Thread-5 (myThread) start
MainThread end
5 6
4 5
Thread-5 (myThread) stop
Thread-3 (myThread) stop
Thread-2 (myThread) stop
Thread-1 (myThread) stop
Thread-4 (myThread) stop
'''

多线程会为每个线程起名字,Thread-1、Thread-2,for循环1,6等于循环了5次,所以就产生了5个新的线程

代码中正常情况下程序会等待一秒,但Thread-1 (myThread) start后就Thread-2 (myThread) start,说明第二个线程启动了,说明了程序是在并行运行,一直到主程序结束后,这些线程才结束


我们发现主线程先结束,然后Thread1-5是后结束的,如果运行时我们希望相互之间有依赖关系,让Thread1-5先结束,然后主线程最后才结束,这种依赖关系称为线程之间的同步

也就是说我们希望一个线程运行的时候能够等待另一个线程结束,这是对线程更高级的控制,上面我们使用函数的方法编写多线程,下面我们来使用面向对象的方式来编写

import threading
'''
start让线程启动,线程启动运行里面的run方法,我们可以使用类的继承,用一个新的类继承threading.Thread
然后利用多态将run方法进行重新
'''
threading.Thread.start()
import threading
from threading import current_thread
'''
什么时候用import threading 什么时候用 from threading import
如果方法非常长的话,推荐使用from import的形式
例如,print(threading.current_thread().name,'start') 比较长,阅读起来不方便
'''

#threading.Thread不要加括号,我们使用的是方法的名称,而不是它的引用
class Mythread(threading.Thread):
  def run(self):
    print(current_thread().name,'start')
    print('run')
    print(current_thread().name,'stop ')

t1 = Mythread()
t1.start()
# 通过join方法,可以让Thread先结束,主线程MainThread后结束
t1.join()

print(current_thread().name,'end')

'''
Thread-1 start
run
Thread-1 stop
MainThread end
'''