线程池与多线程的区别:
- 线程池是在程序运行开始,创建好的n个线程,并且这n个线程挂起等待任务的到来。而多线程是在任务到来得时候进行创建,然后执行任务。
- 线程池中的线程执行完之后不会回收线程,会继续将线程放在等待队列中;多线程程序在每次任务完成之后会回收该线程。
- 由于线程池中线程是创建好的,所以在效率上相对于多线程会高很多。
- 线程池也在高并发的情况下有着较好的性能;不容易挂掉。多线程在创建线程数较多的情况下,很容易挂掉。
1.多线程
Server
from socket import *
import threading
import time
def tcplink(sock, addr):
print('Accept new connection from%s:%s...' % addr)
sock.send(b'Welcome!')
while 1:
data = sock.recv(1024)
time.sleep(1)
if not data or data.decode('utf-8') == 'exit':
break
sock.send(('Hello,%s' % data.decode('utf-8')).encode('utf-8'))
sock.close()
print('Connection from %s:%s closed' % addr)
s = socket(AF_INET, SOCK_STREAM)
s.bind(('127.0.0.1', 9998))
s.listen(5) # 等待连接的最大数量是5
print('The server is ready to receive')
while 1:
# 接收一个新连接
sock, addr = s.accept()
# 创建新线程来处理TCP连接
t = threading.Thread(target=tcplink, args=(sock, addr))
t.start()
while循环内每接收到一个连接,则开启一个线程,并且启动线程,为当前连接的客户端进行服务
Client-1/Client-2
from socket import *
c = socket(AF_INET, SOCK_STREAM)
c.connect(('127.0.0.1', 9998))
# 接收欢迎消息:
print(c.recv(1024).decode('utf-8'))
while 1:
msg = input('please input')
# 防止空消息
if not msg:
continue
c.sendall(msg.encode('utf-8'))
print(c.recv(1024).decode('utf-8'))
# c.send(b'exit')
c.close()
测试
2.线程池
Server
from concurrent.futures import ThreadPoolExecutor
from socket import *
import threading
import time
def tcplink(sock, addr):
print('Accept new connection from%s:%s...' % addr)
sock.send(b'Welcome!')
while 1:
data = sock.recv(1024)
time.sleep(1)
if data.decode('utf-8') == 'exit':
break
sock.send(('Hello,%s' % data.decode('utf-8')).encode('utf-8'))
sock.close()
print('Connection from %s:%s closed' % addr)
s = socket(AF_INET, SOCK_STREAM)
s.bind(('127.0.0.1', 9998))
s.listen(5) # 等待连接的最大数量是5
# 创建线程池 指定工作线程数量为5
pool = ThreadPoolExecutor(max_workers=5)
print('The server-P is ready to receive')
while 1:
# 接收一个新连接
sock, addr = s.accept()
# 创建线程任务,提交到线程池
pool.submit(tcplink, sock, addr)
# 关闭线程池
pool.shutdown(wait=True) # wait=True表示关闭线程池之前需要等待所有工作线程结束
可以发现使用线程池与前面的多线程相比,只是改了三行代码
Clien
则与上面的多线程完全相同