python3自动释放线程_python3-多线程

多线程简介

线程(Thread)也称轻量级进程,时操作系统能够进行运算调度的最小单位,它被包涵在进程之中,时进程中的实际运作单位。线程自身不拥有资源,只拥有一些在运行中必不可少的资源,但他可与同属一个进程的其他线程共享进程所拥有的全部资源。一个线程可以创建和撤销另一个线程,同一进程中的多个线程之间可以并发执行。

线程有就绪/阻塞/运行三种基本状态:

1/ 就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机

2 / 运行状态是指线程占有处理机正在运行。

3/ 阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行

1228783-20190815183930433-1717296218.png

结论:在python中,对于计算密集型任务,多进程占优势;对于I/O密集型任务,多线程占优势

python多线程其它介绍

1/1 多线程threading模块

方法一 创建threading.Thread类的实例,调用其start()方法

方法二 继承Thread类,在子类中重写run()和init()方法

1/2 多线程同步Lock(互诉锁)

#如果多个线程共同对某个数据修改,则可能出现不可预料的结果,这个时候就需要使用互诉锁来进行同步

#调用锁

lock = threading.Lock()

#获取锁,用户线程同步

lock.acquire()

1/3 多线程同步Semaphore(信号量)

互诉锁是只允许一个线程访问共享数据,而信号量是同时允许一定数量的线程访问共享数据

semaphore = threading.BoundedSemaphore()

练习:

import threading

import time

semaphore = threading.BoundedSemaphore(5)

def yewubanli(name):

semaphore.acquire()

time.sleep(3)

print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} {name} 正在办理业务")

semaphore.release()

thread_list = []

for i in range(12):

t = threading.Thread(target=yewubanli, args=(i,))

thread_list.append(t)

for thread in thread_list:

thread.start()

for thread in thread_list:

thread.join()

1/4 多线程同步Condition

条件对象Condition能让一个线程A停下来,等待其它线程B,线程B满足了某个条件后通知(notify)线程A继续运行。线程首先获取一个条件变量锁,如果条件不足,则该线程等待(wait)并释放条件变量锁;如果条件满足,就继续执行线程,执行完成后可以通知(notify)其它状态为wait的线程执行。其它处于wait状态的线程接到通知后会重新判断条件以确定是否继续执行。

cond = threading.Condition()

1/5 多线程同步Event

事件用于线程之间的通信。一个线程发出一个信号,其它一个或多个线程等待,调用Event对象的wait方法,线程则会阻塞等待,直到别的线程set之后才会被唤醒

cond = threading.Event()

1/6 线程优先级队列(queue)

Python的queue模块中提供了同步的/线程安全的队列类,包括先进先出队列Queue/后进后出队列LifoQueue和优先级队列PriorityQueue。这些队列都实现了锁原语,可以直接使用来实现线程之间的同步。

练习:

import threading, time

import queue

q = queue.Queue(maxsize=5)

def ProducerA():

count = 1

while True:

q.put(f"冷饮 {count}")

print(f"{time.strftime('%H:%M:%S')} A 放入:[冷饮 {count}]")

count += 1

time.sleep(1)

def ConsumerB():

while True:

print(f"{time.strftime('%H:%M:%S')} B 取出 [{q.get()}]")

time.sleep(5)

p = threading.Thread(target=ProducerA)

c = threading.Thread(target=ConsumerB)

c.start()

p.start()

1/7 多线程之线程池pool

在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或其它更多资源。虚拟机也将视图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。同样的道理,多任务情况下每次都会生成一个新线程,执行任务后资源再被回收就显得非常低效,因此线程池就是解决这个问题的方法。类似的还有连接池/进程池等。

将任务添加到线程池中,线程池会自动指定一个空闲的线程取执行任务,当超过线程池的最大线程数时,任务需要等待有新的空闲线程后才会被执行。

我们可以使用threading模块及queue模块定制线程池,也可以使用multiprocessing。from multiprocessing import Pool这样导入的Pool表示的时进程池,from multiprocessing.dummy import Pool这样导入的Pool表示的时线程池

练习:

from multiprocessing.dummy import Pool as ThreadPool

import time

def fun(n):

time.sleep(2)

start = time.time()

for i in range(5):

fun(i)

print("单线程顺序执行耗时:", time.time() - start)

start2 = time.time()

pool = ThreadPool(processes=5)

results2 = pool.map(fun, range(5))

pool.close()

pool.join()

print("线程池(5)并发执行耗时:",time.time() - start2)

总结:

Python多线程适合用再I/O密集型任务中。I/O密集型任务较小时间用再CPU计算上,较多时间用再I/O上,如文件读写/web请求/数据库请求等;而对于计算密集型任务,应该使用多进程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值