目录
1.多线程
2.线程对比进程
3.线程间资源共享
4.守护线程
5.线程中常用属性
6.线程互斥锁
7.信号量
8.守护进程的使用
1.多线程
"""
多线程也是用于提高程序的效率
多进程
核心是多道技术
本质上就是切换加保存状态
当程序IO操作较多 可以提高程序效率
多线程
什么是线程
程序的执行线路
相当于与一条流水线,其包含了程序的具体执行步骤
如果我们把操作系统比喻为一个工厂,进程就是车间,先出就是流水线
线程和进程的关系
进程中包含了运行改程序需要所有资源,
*进程是一个资源单位,线程是CPU的最小执行单位*
每一个进程一旦被创建.就默认开启了一条线程,称之为主线程
一个进程可以包含多个线程
进程包含线程 而 线程依赖进程
为什么使用线程
是为了提高程序效率,
为何不用多进程提高效率? 是因为进程对操作系统的资源耗费非常高
线程是如何提高效率的?
多线程可以使CPU在一个进程内进行切换,从而提高CPU占用率
如何使用
两种开启线程的方式
1.实例化Thread类
2.继承Thread类 覆盖run方法
什么情况下应该开启多线程
当程序中遇到IO的时候
当程序中时纯计算任务时 也无法提高效率
进程和线程的区别
1.进程对于操作系统的资源耗费非常高,而线程相反非常低(比进程低10-100倍)
2.在同一个进程,多个线程之间资源是共享的
"""
# 开启线程的第一种方式
from threading import Thread
from multiprocessing import Process
def task():
print("threading running!")
t1 = Thread(target=task)
t1.start()
print("over")
# 第二种方式
class MyThread(Thread):
def run(self):
print("子线程 running....")
MyThread().start()
print("over2")
2.线程对比进程
from multiprocessing import Process
from threading import Thread
import time
def task():
# print("子进程任务....")
pass
# 100个进程时间统计
# if __name__ == '__main__':
# start = time.time()
# ps = []
# for i in range(100):
# p = Process(target=task)
# p.start()
# ps.append(p)
# for p in ps:
# p.join()
# print(time.time()-start)
#100个线程
start = time.time()
ts = []
for i in range(100):
t = Thread(target=task)
t.start()
ts.append(t)
for t in ts:
t.join()
print(time.time()-start)
3.线程间资源共享
from threading import Thread
x = 100
def task():
print("run....")
global x
x = 0
t = Thread(target=task)
t.start()
t.join()
print(x)
print("over")
4.守护线程
"""
守护线程
守护线程会在所有非守护线程结束后结束
三个线程 分贝 皇帝 太子 和皇后
如果把皇后设置为守护线程 那么皇后线程会在 太子和皇帝都死亡后死亡
当所有非线程结束后 守护线程也跟着结束了
进程 守护进程会在被守护进程死亡跟着死亡
同一个进程 可以有多个守护线程
"""
from threading import Thread
#
# import time
#
# def task():
# print("sub thread run....")
# time.sleep(3)
# print("sub thread over....")
#
# t = Thread(target=task)
# t.setDaemon(True)
# t.start()
#
#
# t = Thread(target=task)
# t.setDaemon(True)
# t.start()
#
# print("over!")
from threading import Thread
import time
def task():
print("子线程运行。。。")
time.sleep(1)
print("子线程结束。。。")
t = Thread(target=task)
t.setDaemon(True)
t.start()
# time.sleep(0.1)
print("over")
5.线程中常用属性
from threading import Thread,current_thread,enumerate,active_count
import os
def task():
print("running..")
# print(os.getpid())
# print(current_thread())
print(active_count())
t1 = Thread(target=task)
t1.start()
# print(t1.is_alive())
# print(t1.isAlive())
# print(t1.getName())
# 获取所有线程对象列表
print(enumerate())
# 获取当前线程对象
print(current_thread())
# 获取当前正在运行的线程个数
print(active_count())
# t2 = Thread(target=task)
# t2.start()
6.线程互斥锁
"""
什么时候用锁 当多个进程或多个线程需要同时修改同一份数据时,可能会造成数据的错乱,所以必须得加锁
"""
import time
from threading import Thread,Lock
lock =Lock()
a = 100
def task():
lock.acquire()
global a
temp = a - 1
time.sleep(0.01)
a = temp
lock.release()
ts = []
for i in range(100):
t = Thread(target=task)
t.start()
ts.append(t)
7.信号量
"""
信号量
其实也是一种锁,特点是可以设置一个数据可以被几个线程(进程)共享
与普通锁的区别
普通锁一旦加锁 则意味着这个数据在同一时间只能被一个线程使用
信号量 可以让这个数据在同一时间只能被多个线程使用
使用场景,可以限制一个数据被同时访问的次数,保证程序正常运行
"""
from threading import Semaphore,Thread,current_thread
import time,random
sem = Semaphore(3)
def task():
sem.acquire()
print("%s run..." % current_thread())
time.sleep(3)
sem.release()
for i in range(10):
t = Thread(target=task)
t.start()
8.守护进程的使用
"""
生产者与消费者模型
吃热狗 与 做热狗
"""
import time,random
from multiprocessing import Process,JoinableQueue
def eat_hotdog(name,q):
while True:
res = q.get()
print("%s吃了%s" % (name,res))
time.sleep(random.randint(1,2))
q.task_done() #记录已经被处理的数据的数量
def make_hotdog(name,q):
for i in range(1,6):
time.sleep(random.randint(1, 2))
print("%s生产了第%s个热狗" % (name,i))
res = "%s的%s个热狗" % (name,i)
q.put(res)
# q.put(None)
if __name__ == '__main__':
q = JoinableQueue()
#生产者1
c1 = Process(target=make_hotdog,args=("万达热狗店",q))
c1.start()
#生产者2
c2 = Process(target=make_hotdog, args=("老男孩热狗店", q))
c2.start()
# 消费者
p2 = Process(target=eat_hotdog,args=("思聪",q))
p2.start()
# 首先保证生产者全部产完成
c1.join()
c2.join()
# 保证队列中的数据全部被处理了
q.join() # 明确生产方已经不会再生成数据了