程序默认都是单线程(这个默认线程又叫主线程,其他的线程都叫子线程)
Thread类的对象就是线程对象,程序需要多少个子线程就创建多少个Thread的对象
import time
from datetime import datetime
from threading import Thread,current_thread
模拟电影下载线程:
def download(movie_name:str):
print(f'《{movie_name}》开始下载:{datetime.now()}')
print(current_thread())
time.sleep(2)
print(f'《{movie_name}》下载结束:{datetime.now()}')
单线程下载三部电影
download('天若有情')
download('英雄本色')
download('使徒行者')
多线程下载三部电影
创建子线程:
Thread(target = 函数,args = (元组))
函数 — 需要在子线程中调用的函数
元组 — 调用target对应的函数的时候传递的实参列表
1)、创建线程对象
t1 = Thread(target=download,args=('天若有情',))
t2 = Thread(target=download,args=('英雄本色',))
t3 = Thread(target=download,args=('使徒行者',))
2)、启动线程
线程对象.start()
t1.start()
t2.start()
t3.start()
from threading import Thread,current_thread
import time
from datetime import datetime
class DownLoadThread(Thread):
def __init__(self,movie_name):
super().__init__() #调用父类__init__
self.movie_name = movie_name
def run(self) -> None: #返回值类型说明,none说明没有返回值
print(f'《{self.movie_name}》开始下载:{datetime.now()}')
print(current_thread())
time.sleep(2)
print(f'《{self.movie_name}》下载结束:{datetime.now()}')
download = DownLoadThread('英雄本色')
download1 = DownLoadThread('天若有情')
download2 = DownLoadThread('使徒行者')
# 通过start()调用run(),run()方法会在相应的子线程中调用
download.start()
download1.start()
download2.start()
import time
from datetime import datetime
from threading import Thread,current_thread
from random import randint
join的用法:
线程对象.join() — 等待当前线程的任务结束后才执行后面的代码
def download(movie_name:str):
print(f'《{movie_name}》开始下载:{datetime.now()}')
time.sleep(randint(3,5))
print(f'《{movie_name}》下载结束:{datetime.now()}')
t1 = Thread(target=download,args=('天若有情',))
t2 = Thread(target=download,args=('英雄本色',))
t3 = Thread(target=download,args=('使徒行者',))
t1.start()
t2.start()
t3.start()
#阻塞线程,待t1,t2,t3结束后再执行print()
t1.join()
t2.join()
t3.join()
print('所有电影下载完成!')
import time
from datetime import datetime
from multiprocessing import Process,current_process
from random import randint
def download(movie_name:str):
print(f'《{movie_name}》开始下载:{datetime.now()}')
print(current_process())
time.sleep(randint(3,5))
print(f'《{movie_name}》下载结束:{datetime.now()}')
多进程必须写在 _ name_ = = ’ _ main_’
if __name__ == '__main__':
p1 = Process(target=download,args=('天若有情',))
p2 = Process(target=download,args=('英雄本色',))
p3 = Process(target=download,args=('使徒行者',))
p1.start()
p2.start()
p3.start()
from threading import Thread,current_thread
结论:在子线程中调用的函数如果有返回,这个返回值无法在任何地方获取
data = []
def download(name):
print('*****')
data.append(f'{name}') #收集数据
def use_data():
for x in data:
print(f'使用{current_thread()}:{x}')
thread1 = Thread(target=download,args=('使徒行者',))
thread2 = Thread(target=download,args=('英雄本色',))
thread3 = Thread(target=use_data)
thread1.start()
thread2.start()
thread3.start()
thread1.join()
thread2.join()
thread3.join()
print(data)
from threading import Thread,Lock,RLock
import time
同一个进程中的多个线程间的数据可以直接相互使用
data = 100
list1 = []
def func1():
time.sleep(2)
global data
print(data)
data = 999
list1.append(200)
thread = Thread(target=func1)
thread.start()
# thread.join() #100
# 999 [200]
print(data,list1) #100 [] 100
time.sleep(5)
加锁:一个数据一个锁(数据和锁需要对应)
1)、创建锁对象,保证一个数据一个锁
lock对象:锁对象.acquire() — 加锁;
锁对象.release() — 释放锁
RLock对象: — 自动解锁
with 锁对象:
操作数据的代码段
lock = Lock()
lock2 = RLock()
def save_money(num:int):
# 2、在使用需要锁的数据之前加锁
lock.acquire()
global balance
b1 = balance
time.sleep(2)
balance = b1 + num
# 3、数据使用完后释放锁(解锁)
lock.release()
print(f'当前账户余额为:{balance}')
def draw_money(num:int):
lock.acquire()
global balance
b1 = balance
if(b1 > num):
time.sleep(2)
balance = b1 - num
else:
print('余额不足!')
print(f'当前账户余额为:{balance}')
lock.release()
thread_s = Thread(target=save_money,args=(2000,))
thread_d = Thread(target=draw_money,args=(3000,))
thread_s.start()
thread_d.start()
import requests
from lxml import etree
from threading import Thread
def get_one_page(page: int):
print(f'获取第{page}页数据')
if page == 1:
url = 'https://pic.netbian.com/index.html'
else:
url = f'https://pic.netbian.com/index_{page}.html'
response = requests.get(url)
response.encoding = 'gbk'
html = etree.HTML(response.text)
result = html.xpath('//div[@class="slist"]/ul/li/a/img/@src|//div[@class="slist"]/ul/li/a/span/img/@src')
# return ['https://pic.netbian.com'+x for x in result]
# 一页图片用一个线程来下载
t = Thread(target=download_page_image, args=(['https://pic.netbian.com'+x for x in result],))
t.start()
# 一张图片一个线程
# for url in ['https://pic.netbian.com'+x for x in result]:
# t = Thread(target=download_image, args=(url,))
# t.start()
def get_all_data():
for page in range(1, 11):
t = Thread(target=get_one_page, args=(page, ))
t.start()
def download_page_image(urls: list):
print(f'下载一页数据:{len(urls)}')
for url in urls:
download_image(url)
def download_image(url: str):
response = requests.get(url)
f = open(f'files/{url.split("/")[-1]}', 'wb')
f.write(response.content)
# print('下载完成!')
get_all_data()
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/Lemon_Review/article/details/119763199
内容来源于网络,如有侵权,请联系作者删除!