目录:
线程理论
1.什么是线程?
进程:资源单位(起一个进程仅仅只是在内存中开辟一块空间)
线程:执行单位(真正被cpu执行的其实是线程,线程其实指的就是代码的执行过程,执行代码中需要的数据找进程这个资源单位要!)
也就意味着进程中真正在执行功能的其实是它里面的线程,即每个进程内部都必须起码有一个线程
2.为什么要有线程?
- 同一个进程下的多个线程共享该进程内的资源
- 创建线程的开销要远远小于进程
开启线程的两种方式
from threading import Thread
import time
# 第一种方式
def task(name):
print('%s is running' % name)
time.sleep(3)
print('%s is end' % name)
t = Thread(target=task, args=('jason',))
t.start() # 创建线程 这句话一运行完 线程几乎就已经创建完毕了
print('主')
# 第二种方式
class MyThread(Thread):
def __init__(self, name):
super().__init__()
self.name = name
def run(self):
print('%s is running' % self.name)
time.sleep(3)
print('%s is end' % self.name)
t = MyThread('jason')
t.start()
print('主')
线程对象的属性和方法
# 1.验证线程之间数据共享
from threading import Thread
import time
n=100
def task():
global n
n=0
if __name__ == '__main__':
t=Thread(target=task)
t.start()
t.join()
print('主',n)
# 2.线程之间os.getpid() >>> 相等
from threading import Thread
import time,os
def task():
print('%s is running' %os.getpid())
if __name__ == '__main__':
t=Thread(target=task)
t.start()
print('主',os.getpid())
# 3.active_count当前活跃的线程个数,当前线程
from threading import Thread,active_count,current_thread
import time,os
def task():
print('%s is running' %current_thread().name)
time.sleep(2)
if __name__ == '__main__':
t=Thread(target=task,)
t.start()
# t.join()
# print('主',active_count())
print('主',current_thread().name)
守护线程
# 进程自带的那个线程运行结束,守护线程立即结束
"""
主线程会等待所有非守护线程的结束,原因在于主线程结束意味着当前进程结束,空间资源均被回收
很明显子线程可能还在运行,明显不合理!
"""
from threading import Thread
import time
def task(name):
print('%s is running' %name)
time.sleep(2)
print('%s is done' %name)
if __name__ == '__main__':
t=Thread(target=task,args=('线程1',))
t.daemon=True
t.start()
print('主')
# 稍微有点迷糊人的例子
from threading import Thread
from multiprocessing import Process
import time
def foo():
print(123)
time.sleep(1)
print("end123")
def bar():
print(456)
time.sleep(3)
print("end456")
if __name__ == '__main__':
t1=Thread(target=foo)
t2=Thread(target=bar)
t1.daemon=True
t1.start()
t2.start()
print("main-------")
"""
123
456
main-------
end123
end456
"""
线程互斥锁
from threading import Thread,Lock
import time
mutex=Lock() # 创建线程不需要从头到位再执行代码拷贝数据
n=100
def task():
global n
mutex.acquire()
temp=n
time.sleep(0.1)
n=temp-1
mutex.release()
if __name__ == '__main__':
t_l=[]
for i in range(100):
t=Thread(target=task)
t_l.append(t)
t.start()
for t in t_l:
t.join()
print(n)
互斥锁与递归锁
from threading import Thread,Lock,RLock
import time
# mutexA=Lock()
# mutexB=Lock()
mutexB=mutexA=RLock()
class Mythead(Thread):
def run(self):
self.f1()
self.f2()
def f1(self):
mutexA.acquire()
print('%s 抢到A锁' %self.name)
mutexB.acquire()
print('%s 抢到B锁' %self.name)
mutexB.release()
mutexA.release()
def f2(self):
mutexB.acquire()
print('%s 抢到了B锁' %self.name)
time.sleep(2)
mutexA.acquire()
print('%s 抢到了A锁' %self.name)
mutexA.release()
mutexB.release()
if __name__ == '__main__':
for i in range(100):
t=Mythead()
t.start()
线程池
from concurrent.futures import ThreadPoolExecutor
import time
import os
# 实例化池对象
# 不知道参数的情况,默认是当前计算机cpu个数乘以5,也可以指定线程个数
pool = ThreadPoolExecutor(20) # 创建了一个线程池子,池子里面有20个线程
# pool = ProcessPoolExecutor(5) # 创建了一个池子
def task(n):
print(n,os.getpid())
time.sleep(2)
return n**2
def call_back(n):
print('我拿到了结果:%s'%n.result())
"""
提交任务的方式
同步:提交任务之后,原地等待任务的返回结果,再继续执行下一步代码
异步:提交任务之后,不等待任务的返回结果(通过回调函数拿到返回结果并处理),直接执行下一步操作
"""
# 回调函数:异步提交之后一旦任务有返回结果,自动交给另外一个去执行
if __name__ == '__main__':
# pool.submit(task,1)
t_list = []
for i in range(20):
future = pool.submit(task,i).add_done_callback(call_back) # 异步提交任务
t_list.append(future)
# pool.shutdown() # 关闭池子并且等待池子中所有的任务运行完毕
# for p in t_list:
# print('>>>:',p.result())
print('主')