python100 - day27 - ThreadAndProcess

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}下载结束!')
    # 返回‘肖申克的救赎’二进制
	# return 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、创建线程池对象
# ThreadPool(线程的数量)
pool = threadpool.ThreadPool(10)
3、在线程池中添加任务
# 线程池对象.putRequest(任务对象)
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 = []
    # 1.创建进程对象
    p1 = Process(target=download, args=('让子弹飞',))
    p2 = Process(target=download, args=('赌神',))
    p3 = Process(target=download, args=('活着',))

    # 2.开始执行进程中的任务
    p1.start()
    p2.start()
    p3.start()

    # 3.等待
    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__':
    # 1.创建进程池
    # Pool(进程数量)
    pool = Pool(3)

    # 2.添加任务(任务添加完成后会自动启动)
    # 1)一次性添加多个任务(和主进程同步执行)
    # 进程池对象.map(函数, 参数列表)
    # pool.map(download, [f'电影{x+1}' for x in range(20)])
    # 2)一次添加一个任务
    # apply()  -  添加的任务和主进程中的任务同步执行
    # apply_async()  -  添加的任务和主进程中的任务异步
    pool.apply_async(download, ('肖生克的救赎',))
    pool.apply_async(download, ('电影001',))
    pool.apply_async(download, ('电影002', ))

    # 3.关闭进程池
    # 进程池关闭后不能再往进程池中添加任务
    pool.close()
    # pool.apply(download, ('恐怖游轮',))

    for x in range(100):
        print(x)

    # 4.等待
    pool.join()
    print('===================================')
11、线程和进程一起用
from multiprocessing import Pool
from threadpool import ThreadPool,makeRequests
import time

# 用三个进程,每个进程中有10个线程来下载200个电影


def download(name):
    print(f'开始下载{name}')
    time.sleep(1)
    print(f'{name}下载结束')


def create_thread(names):
    # 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'=====================结束===================')
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值