python100 - day27 - ThreadAndProcess
1、线程安全
from threading import Thread, current_thread
import time
1.多个线程可以直接操作同一个进程中的同一个数据
num = 200
print ( '定义:' , current_thread( ) )
def add_num ( ) :
global num
num += 100
global name
name = '张三'
print ( '操作:' , current_thraed)
t = Thread( target= add_num)
t. start( )
t. join( )
print ( num)
print ( name)
2.数据安全(起因:多个线程可以同时操作同一个数据)
account = 10000
def save ( num) :
print ( '开始存钱' )
global account
balance = account
time. sleep( 2 )
account = balance+ num
print ( f'存钱成功!当前余额:{account}' )
def draw ( num) :
print ( '开始取钱!' )
global account
balance = account
if balance < num:
print ( '余额不足!' )
return
time. sleep( 2 )
account = balance - num
print ( f'取钱成功!当前余额:{account}' )
t1 = Thread( target= save, args= ( 20000 , ) )
t2 = Thread( taeget= draw, args= ( 5000 , ) )
t2. start( )
t1. start( )
t1. join( )
t2. join( )
print ( account)
2、LOCK锁
from threadind import Thread, current_thread, LOCK
import time
1.怎么加锁
"""
1)保证一个数据对应一个锁对象
锁对象 = Lock()
2)线程在第一次操作数据前加锁
锁对象.acquire()
3)线程在操作数据结束后解锁
锁对象.release()
"""
account = 10000
account_lock = Lock( )
def save ( num) :
print ( '开始存钱!' )
global account
account_lock. acquire( )
balance = account
time. sleep( 2 )
account = balance + num
print ( f'存钱成功!当前余额:{account}' )
account_lock. release( )
def draw ( num) :
print ( '开始取钱!' )
global account
account_lock. acquire( )
balance = account
if balance < num:
print ( '余额不足' )
return
time. sleep( 2 )
account = balance - num
print ( '取钱成功!当前余额:{account}' )
account_lock. release( )
t1 = Thread( target= save, args= ( 20000 , ) )
t2 = Thread( target= draw, args= ( 5000 ) , )
t2. start( )
t1. start( )
t1. join( )
t2. join( )
print ( account)
3、RLOCK锁
from threading import Thread, current_thread, RLock
import time
1.怎么加锁
"""
1)保证一个数据对应一个锁对象
锁对象 = RLock()
2)将对数据进行操作的代码放到锁的范围内
with 锁对象:
操作数据的代码
"""
account = 10000
account_lock = RLock
def save ( num) :
print ( '开始存钱!' )
with account_lock:
global account
time. sleep( 2 )
balance = account
account = balance + num
print ( '存钱成功!' )
def draw ( num) :
print ( '开始取钱!' )
with account_lock:
global account
balance = account
if balance < num:
print ( '余额不足!' )
return
time. sleep( 2 )
account = balance - num
print ( '取钱成功!' )
t1 = Thread( target= save, args= ( 20000 , ) )
t2 = Thread( target= draw, args= ( 5000 ) , )
t2. start( )
t1. start( )
t1. join( )
t2. join( )
print ( account)
4、多线程数据收集
import time
from threading import Thread
from random import randint
1.收集线程数据:定义一个全局的可变容器,最好是队列(python中的队列本身是线程安全)将线程中产生的数据添加到容器中
result = [ ]
def download ( name) :
print ( f'{name}开始下载!' )
time. sleep( randint( 2 , 7 ) )
print ( f'{name}下载结束!' )
result. append( f'{name}' 的二进制)
t1 = Thread( target= download, args= ( '肖申克的救赎' , ) )
t2 = Thread( target= download, args= ( '十二生肖' , ) )
t3 = Thread( target= download, args= ( '这个杀手不太冷' , ) )
re1 = t1. start( )
t2. start( )
t3. start( )
t1. join( )
t2. join( )
t3, join( )
print ( 're1:' , re1)
print ( result)
5、队列的使用
from queue import Queue
from threading import Thread
import time
from random import randint
1、什么是队列
1)Queue(队列)是一种容器,一般用于多线程和多进程的数据共享,因为Queue对象本身是线程安全
2)获取队列中的元素的时候,如果没有元素会等待,直到队列中有元素为止
2、操作队列
1)添加元素:队列对象.put(元素)
2)获取元素(取一个就少一个):队列对象.get()
queue = Queue( )
def add ( ) :
for x in range ( randint( 50 , 100 ) ) :
queue. put( x)
print ( f'添加数据{x}' )
def get ( ) :
while True :
print ( f'得到数据:{queue.get()}' )
t1 = Thread( target= add)
t2 = Thread( target= get)
t1. start( )
t1. join( )
print ( '=========添加完成!=========' )
queue. put( 'end' )
print ( queue. qsize( ) )
while True :
re = queue. get( )
if re == 'end' :
break
print ( re)
6、线程池
import threadpool
import time
from datetime import datetime
from threading import current_thread, Thread
from queue import Queue
q = Queue( )
def download ( name) :
print ( f'{name}开始下载' , datetime. now( ) )
print ( current_thread( ) )
time. sleep( 1 )
print ( f'{name}下载结束' , datetime. now( ) )
q. put( name)
def save ( num) :
print ( '============================开始保存==========================' )
while True :
print ( '======保存数据的线程======' , current_thread( ) )
result = q. get( )
print ( f'=======保存{result}成功!' )
1、创建任务列表
makeRequests(任务对应的函数, 参数列表) - 创建任务列表
注意:
1)任务函数有且只有一个参数
2)参数列表中元素的个数决定了任务列表中任务的个数
tasks = threadpool. makeRequests( download, [ f'电影:{x}' for x in range ( 100 ) ] )
tasks2 = threadpool. makeRequests( save, [ 0 ] )
2、创建线程池对象
pool = threadpool. ThreadPool( 10 )
3、在线程池中添加任务
for task in tasks2:
pool. putRequest( task)
for task in tasks:
pool. putRequest( task)
4、执行和等待
相当于先start 然后 join
pool. wait( )
print ( '=======================下载结束========================' )
7、线程池和线程一起使用
import threadpool
import time
from datetime import datetime
from threading import current_thread, Thread
from queue import Queue
q = Queue( )
def download ( name) :
print ( f'{name}开始下载' , datetime. now( ) )
time. sleep( 1 )
print ( f'{name}下载结束' , datetime. now( ) )
q. put( name)
def save ( ) :
print ( '======================开始保存=========================' )
data = [ ]
while True :
result = q. get( )
if result == 'end' :
break
data. append( result)
print ( len ( data) , data)
1.在线程池中添加下载任务
tasks = threadpool. makeRequests( download, [ f'电影{x}' for x in range ( 100 ) ] )
pool = threading. ThreadPool( 20 )
for task in tasks:
pool. putRequest( task)
2.在一个独立的线程中添加保存任务
t = Thread( target= save)
t. start( )
3.执行和等待
pool. wait( )
q. put( 'end' )
print ( '=========================下载结束=========================' )
8、多进程
from multiprocessing import Process
import time
from datetime import datetime
from threading import Thread
def download ( name) :
global a
a += 100
list1. append( name)
print ( 'a:' , a)
print ( f'{name}开始下载!' , datetime. now( ) )
time. sleep( 1 )
print ( f'{name}开始结束!' , datetime. now( ) )
if __name__ == '__main__' :
a = 100
list1 = [ ]
p1 = Process( target= download, args= ( '让子弹飞' , ) )
p2 = Process( target= download, args= ( '赌神' , ) )
p3 = Process( target= download, args= ( '活着' , ) )
p1. start( )
p2. start( )
p3. start( )
p1. join( )
p2. join( )
p3. join( )
print ( '===============进程都结束==================' )
print ( a, list1)
10、进程池
from multiprocessing import Pool
from datetime import datetime
import time
def download ( name) :
print ( f'{name}开始下载!' , datetime. now( ) )
time. sleep( 1 )
print ( f'{name}开始结束!' , datetime. now( ) )
if __name__ == '__main__' :
pool = Pool( 3 )
pool. apply_async( download, ( '肖生克的救赎' , ) )
pool. apply_async( download, ( '电影001' , ) )
pool. apply_async( download, ( '电影002' , ) )
pool. close( )
for x in range ( 100 ) :
print ( x)
pool. join( )
print ( '===================================' )
11、线程和进程一起用
from multiprocessing import Pool
from threadpool import ThreadPool, makeRequests
import time
def download ( name) :
print ( f'开始下载{name}' )
time. sleep( 1 )
print ( f'{name}下载结束' )
def create_thread ( names) :
t_pool = ThreadPool( 10 )
tasks = makeRequests( download, names)
for t in tasks:
t_pool. putRequest( t)
t_pool. wait( )
if __name__ == '__main__' :
pool = Pool( )
tasks = [ ]
ts = [ ]
for x in range ( 1 , 200 + 1 ) :
ts. append( x)
if x % 50 == 0 :
tasks. append( ts)
ts = [ ]
pool. map ( create_thread, tasks)
print ( f'=====================结束===================' )