线程
线程的特点:
- 多个线程共享同一个进程的内存空间
- 开启一个线程开销比进程小很多
- 所有进程运行的最小单位就是线程
进程和线程的区别
- 线程开启速度快
- 同一个进程下的所有线程有相同的PID.
- 同一个进程下的朵儿线程共享数据
开启线程的方式
开启线程的方式和开启进程的方式类似,可以通过自定义类或者导入模块的方式。
方式一
导入模块:
from threading import Thread
import time
import random
def piao(name):
print('%s is piaoing' %name)
time.sleep(random.randint(1,3))
print('%s is piao end' %name)
if __name__=='__main__':
t1=Thread(target=piao,args=('bob',))
t1.start()
print('主')
输出:
bob is piaoing
主
bob is piao end
由于开启线程的开销小,所以线性会先执行。
方式二
通过自定义类:
from threading import Thread
import time
import random
class MyThread(Thread):
def __init__(self,name):
super().__init__()
self.name=name
def run(self):
print('%s is piaoing' %self.name)
time.sleep(random.randint(1,3))
print('%s is piao end' %self.name)
if __name__=='__main__':
t1=MyThread('bob')
t1.start()
print('主')
输出:
bob is piaoing
主
bob is piao end
多线程实现并发网络套接字通信
# 服务端
from socket import *
from threading import Thread,current_thread
def comunicate(conn):
print('子线程: %s' %current_thread().getName())
while True:
try:
data = conn.recv(1024)
if not data: break
conn.send(data.upper())
except ConnectionResetError:
break
conn.close()
def server(ip,port):
print('主线程:%s' %current_thread().getName())
server = socket(AF_INET,SOCK_STREAM)
server.bind((ip,port))
server.listen(5)
while True:
conn,addr = server.accept()
print(addr)
t = Thread(target=comunicate,args=(conn,))
t.start()
server.close()
if __name__=='__main__':
server('127.0.0.1',8080)
# 客户端
from socket import *
client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080))
while True:
msg = input('>>:').strip()
if not msg: continue
client.send(msg.encode('utf-8'))
data=client.recv(1024)
print(data.decode('utf-8'))
client.close()
守护线程
无论是进程还是线程,都遵循: 守护线程/进程会等待主线程/进程运行完毕后被销毁。
这里的运行完毕指的是:
- 对主进程来说,运行完毕指的是主进程代码运行完毕。
- 对主线程来说,运行完毕时主线程所在的进程内所有非守护线程都运行完毕,主线程才算运行完毕。
示例:
from threading import Thread
import time
def sayhi(name):
print('子线程开启...')
time.sleep(2)
print('%s say hello' %name)
if __name__=='__main__':
t=Thread(target=sayhi,args=('andy',))
t.setDaemon(True) # 等效 t.daemon=True
t.start()
print('主线程结束')
输出:
子线程开启...
主线程结束
设置为守护线程后,主线程结束子线程也会立即结束。
如下示例:
# coding=utf-8
import os
from threading import Thread
import time
def foo():
print('这是守护线程')
time.sleep(3)
print('守护线程结束')
def bar():
print('这是普通子线程')
time.sleep(2)
print('bar 运行结束')
if __name__ == '__main__':
p1=Thread(target=foo)
p2=Thread(target=bar)
p1.daemon=True
p1.start()
p2.start()
print("主线程到此结束!")
输出结果:
这是守护线程
这是普通子线程
主线程到此结束!
bar 运行结束