from threading import Thread
import time
deftask(name):
print(f'{name}任务开始')
time.sleep(2)
print(f'{name}任务结束')
if __name__ == '__main__':
t = Thread(target=task, args=('学习',))
t.start()
print('主线程')
from threading import Thread
import time
classMyThread(Thread):
def__init__(self, name):
super().__init__()
self.name = name
defrun(self) -> None:
print(f'{self.name}任务开始')
time.sleep(2)
print(f'{self.name}任务结束')
if __name__ == '__main__':
t = MyThread(name='打篮球')
t.start()
print('主线程')
用法基本和multiprocessing模块,也就是创建进程的方式一模一样
【三】查看ID
用threading模块里面的current_thread方法
from threading import Thread,current_thread
import time
deftask(name):
print(f'{name}任务开始')
print(current_thread().native_id)
time.sleep(2)
print(f'{name}任务结束')
if __name__ == '__main__':
t = Thread(target=task, args=('学习',))
t.start()
print('主线程')
用os模块里面的getpid()方法
from threading import Thread
import time
from os import getpid
deftask(name):
print(f'{name}任务开始')
print(getpid())
time.sleep(2)
print(f'{name}任务结束')
if __name__ == '__main__':
t = Thread(target=task, args=('学习',))
t.start()
print('主线程')
【四】多线程并发的socket服务端
服务端
from threading import Thread
import socket
from socket import SOL_SOCKET, SO_REUSEADDR
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
server.bind(('127.0.0.1', 8080))
server.listen(5)
deftalk(conn):
whileTrue:
try:
msg = conn.recv(1024).decode('utf-8')
print(f'客户端:>>>>{msg}')
conn.send(msg.upper().encode('utf-8'))
except Exception as error:
print(error)
break
conn.close()
defthreading_version(conn):
t = Thread(target=talk, args=(conn,))
t.start()
defmain_threading():
whileTrue:
conn, addr = server.accept()
threading_version(conn=conn)
if __name__ == '__main__':
main_threading()
客户端(不变)
from socket import *
# 不写参数:默认是TCP协议# (1)创建客户端对象
client = socket()
# (2)绑定 IP PORT# (2)建立链接桥梁 --(呼应客户端的 ip 和 port)
IP = '127.0.0.1'
PORT = 8080
client.connect((IP, PORT))
# (4)链接循环whileTrue:
# (4.1)向服务端发数据
msg_to_server = input('请输入消息:>>>>').strip()
ifnot msg_to_server:
continue
client.send(msg_to_server.encode('utf-8'))
# 接受服务器返回的数据
data_from_server = client.recv(1024)
print(data_from_server.decode('utf-8'))
if msg_to_server == 'q':
break
client.close()
【五】单进程,多进程,多线程速度比较
通过一个爬虫案例
import requests
import os
import time
from lxml import etree
from multiprocessing import Process
from threading import Thread
deftimer(func):
definner(*args, **kwargs):
start_time = time.time()
func(*args, **kwargs)
print(f'总耗时{time.time() - start_time}秒')
return inner
defcreate_url_list():
url_list = []
for i inrange(1, 6):
if i == 1:
url = 'https://pic.netbian.com/4kmeinv/'
url_list.append(url)
else:
url = f'https://pic.netbian.com/4kmeinv/index_{i}.html'
url_list.append(url)
return url_list
defspider_data(url_list):
data_dic = []
for url in url_list:
response = requests.get(url=url)
response.encoding = 'gbk'
response_text = response.text
html_obj = etree.HTML(response_text)
li_list = html_obj.xpath('//*[@id="main"]/div[3]/ul/li')
for li in li_list:
src = "https://pic.netbian.com/" + li.xpath('./a/img/@src')[0]
title = li.xpath('./a/b/text()')[0]
data_dic.append({'src': src, 'title': title})
return data_dic
defsave_data(file_title, file_src):
file_name = 'image'
file_path = os.path.join(os.path.dirname(__file__), file_name)
os.makedirs(file_path, exist_ok=True)
file_path = os.path.join(file_path, f'{file_title}.png')
data = requests.get(file_src)
withopen(file_path, 'wb') as fp:
fp.write(data.content)
print(f'当前图片{file_title}保存完成')
@timerdefmain_normal():
url_list = create_url_list()
data_list = spider_data(url_list=url_list)
for data in data_list:
image_src = data.get('src')
image_title = data.get('title')
save_data(image_title, image_src)
@timerdefmain_process():
url_list = create_url_list()
data_list = spider_data(url_list=url_list)
p_list = []
for data in data_list:
image_src = data.get('src')
image_title = data.get('title')
p = Process(target=save_data, args=(image_title, image_src))
p.start()
p_list.append(p)
for p in p_list:
p.join()
@timerdefmain_thread():
url_list = create_url_list()
data_list = spider_data(url_list=url_list)
p_list = []
for data in data_list:
image_src = data.get('src')
image_title = data.get('title')
p = Thread(target=save_data, args=(image_title, image_src))
p.start()
p_list.append(p)
for p in p_list:
p.join()
if __name__ == '__main__':
...
# main_normal() 34s# main_process() 9.7s# main_thread() 7s
可以看到在多IO阻塞时的速度比较结果为
多线程>多进程>单进程
【六】线程之间数据共享
from threading import Thread
age = 20deftask():
global age
age -= 2print(f'我是子线程的age:>>>>{age}')
if __name__ == '__main__':
t = Thread(target=task, args=())
t.start()
print(f'我是主线程的age:>>>>{age}')
'''
我是子线程的age:>>>>18
我是主线程的age:>>>>18
'''
可以看到我在子线程中修改了主线程的age
主线程的age也修改了
说明线程之间数据共享
【七】不同的线程的进程ID是相同的
from threading import Thread
import os
age = 20deftask():
global age
age -= 2print(f'我是子线程的age:>>>>{age}')
print(f'进程ID:>>>>{os.getpid()}')
if __name__ == '__main__':
t = Thread(target=task, args=())
t.start()
print(f'我是主线程的age:>>>>{age}')
print(f'进程ID:>>>>{os.getpid()}')
'''
进程ID:>>>>15792
进程ID:>>>>15792
'''
【八】查看线程名称
首先要导入threading模块下的current_thread方法
通过这个方法.name就可以拿到当前线程的名称
from threading import Thread, current_thread
deftask(i):
print(f'线程程{i}名称:>>>>{current_thread().name}')
if __name__ == '__main__':
t = [Thread(target=task, args=(i,)).start() for i inrange(1, 6)]
print(f'主线程名称:>>>>{current_thread().name}')
'''
线程程1名称:>>>>Thread-1 (task)
线程程2名称:>>>>Thread-2 (task)
线程程3名称:>>>>Thread-3 (task)
线程程4名称:>>>>Thread-4 (task)
线程程5名称:>>>>Thread-5 (task)
主线程名称:>>>>MainThread
'''
【九】查看活跃的线程数量
首先要导入threading模块下的active_count方法
from threading import Thread, current_thread, active_count
import time
deftask(i):
print(f'线程程{i}名称:>>>>{current_thread().name}')
time.sleep(2)
if __name__ == '__main__':
t = [Thread(target=task, args=(i,)).start() for i inrange(1, 6)]
print(f'主线程名称:>>>>{current_thread().name}')
print(f'当前活动线程的数量{active_count()}')
'''
线程程1名称:>>>>Thread-1 (task)
线程程2名称:>>>>Thread-2 (task)
线程程3名称:>>>>Thread-3 (task)
线程程4名称:>>>>Thread-4 (task)
线程程5名称:>>>>Thread-5 (task)
主线程名称:>>>>MainThread
当前活动线程的数量6
'''
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!