一、python线程模块的选择
Python提供了几个用于多线程编程的模块,包括thread、threading和Queue等。thread和threading模块允许程序员创建和管理线程。thread模块提供了基本的线程和锁的支持,threading提供了更高级别、功能更强的线程管理的功能。Queue模块允许用户创建一个可以用于多个线程之间共享数据的队列数据结构。
避免使用thread模块,因为更高级别的threading模块更为先进,对线程的支持更为完善,而且使用thread模块里的属性有可能会与threading出现冲突;其次低级别的thread模块的同步原语很少(实际上只有一个),而threading模块则有很多;再者,thread模块中当主线程结束时,所有的线程都会被强制结束掉,没有警告也不会有正常的清除工作,至少threading模块能确保重要的子线程退出后进程才退出。
thread模块不支持守护线程,当主线程退出时,所有的子线程不论它们是否还在工作,都会被强行退出。而threading模块支持守护线程,守护线程一般是一个等待客户请求的服务器,如果没有客户提出请求它就在那等着,如果设定一个线程为守护线程,就表示这个线程是不重要的,在进程退出的时候,不用等待这个线程退出。
二、threading模块
multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性,因而不再详细介绍(官方链接)
三、通过threading.Thread类创建线程
3.1 创建线程的方式一
1 2 3 4 5 6 7 8 9 10
|
from threading import Thread import time def sayhi(name): time.sleep(2) print('%s say hello' %name)
if __name__ == '__main__': t=Thread(target=sayhi,args=('nick',)) t.start() print('主线程')
|
3.2 创建线程的方式二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
from threading import Thread import time class Sayhi(Thread): def __init__(self,name): super().__init__() self.name=name def run(self): time.sleep(2) print('%s say hello' % self.name)
if __name__ == '__main__': t = Sayhi('nick') t.start() print('主线程')
|
四、多线程与多进程
4.1 pid的比较
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
from threading import Thread from multiprocessing import Process import os
def work(): print('hello',os.getpid())
if __name__ == '__main__':
|
4.2 开启效率的较量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
from threading import Thread from multiprocessing import Process import os
def work(): print('hello')
if __name__ == '__main__':
|
4.3 内存数据的共享问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
from threading import Thread from multiprocessing import Process import os def work(): global n n=0
if __name__ == '__main__':
|
五、Thread类的其他方法
Thread实例对象的方法:
isAlive()
:返回线程是否活动的。
getName()
:返回线程名。
setName()
:设置线程名。
threading模块提供的一些方法:
threading.currentThread()
:返回当前的线程变量。
threading.enumerate()
:返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount()
:返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
5.1 代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
from threading import Thread import threading from multiprocessing import Process import os
def work(): import time time.sleep(3) print(threading.current_thread().getName())
if __name__ == '__main__':
|
5.2 join方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
from threading import Thread import time def sayhi(name): time.sleep(2) print('%s say hello' %name)
if __name__ == '__main__': t=Thread(target=sayhi,args=('nick',)) t.start() t.join() print('主线程') print(t.is_alive()) ''' nick say hello 主线程 False '''
|
六、多线程实现socket
6.1 服务端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
import multiprocessing import threading
import socket s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.bind(('127.0.0.1',8080)) s.listen(5)
def action(conn): while True: data=conn.recv(1024) print(data) conn.send(data.upper())
if __name__ == '__main__':
while True: conn,addr=s.accept()
p=threading.Thread(target=action,args=(conn,)) p.start()
|
6.2 客户端
1 2 3 4 5 6 7 8 9 10 11 12
|
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect(('127.0.0.1',8080))
while True: msg=input('>>: ').strip() if not msg:continue
s.send(msg.encode('utf-8')) data=s.recv(1024) print(data)
|