线程
时间:2019-12-14
本文章向大家介绍线程,主要包括线程使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
参考链接: https://www.cnblogs.com/Eva-J/articles/8306047.html
threading
单线程
import time from threading import Thread def func(n): time.sleep(1) print(n) if __name__ == "__main__": # 创建一个子线程 t = Thread(target=func, args=(1,)) t.start()
多线程
主线程会等子线程执行完毕后再结束
import time from threading import Thread # 多线程并发 def func(n): time.sleep(5) print('我是子线程',n) for i in range(10): # 主线程会等子线程执行完毕后再结束 t = Thread(target=func, args=(i,)) t.start() print('我是主线程')
类方法使用线程
import time from threading import Thread # 多线程并发 class MyTread(Thread): # 要使用新属性时需要调用父类的init def __init__(self,args): super().__init__() self.args = args # 一定要创建一个类方法 def run(self): time.sleep(1) print(self.args) t = MyTread(10) t.start()
ps:
#进程是最小的内存分配单位。
#线程是 操作系统调度的最小单位。
#线程被CPU执行了。
#进程内至少含有一个线程。
#进程中可以开启多个线程。
#开启一个线程所需要的时间要远远小于开启一个进程。
#多个线程内部有自己的数据栈,数据不共享。
#全局变量在多个线程之间是共享的。
#在Cpython解释器下的python程序 在同一时刻 多个线程中只能有一个线程被CPU执行。GIL锁(全局解释器锁)
#高CPU :计算类——高CPU利用率。
#高IO :爬取网页 200个网页
#qq聊天 send recv 处理日志文件 读文件 处理web请求 读数据库
全局变量在多线程中是共享的
import time import os from threading import Thread # 多线程并发 def func(a, b): global g g = 0 n = a + b # 调用这个子线程之后,由于他声明了全部变量 所以这个g = 0 g = 100 lst = [] for i in range(1): # 开启一个子线程 t = Thread(target=func, args=(i, 5)) t.start() # 我这里只是为了取一个循环次数 lst.append(t) for t in lst: # 等子线程 执行完之后再执行 主线程 t.join() #全局变量在线程之间是共享的 print('主线程', g)
多进程和多线程时间对比
这差距不是一般的大呀!!!!
线程socket:可以连接多个client
client
线程模块中的其他方法
# 查看当前活跃线程数加上主线程 #10 +
print(threading.active_count())
# 查看是否属于主线程还是子线程
print(threading.current_thread())
# 显示所有线程名和id
print(threading.enumerate())
# get_ident 是查看线程id
print(threading.get_ident())
import time import os from threading import Thread import threading # 多线程并发 def func(n): time.sleep(0.5) # 查看是否属于主线程还是子线程 print(i,threading.current_thread()) # get_ident 是查看线程id print(threading.get_ident()) for i in range(10): t = threading.Thread(target=func,args=(i,)) t.start() # 查看当前活跃线程数加上主线程 #10 + print(threading.active_count()) # 查看是否属于主线程还是子线程 print(threading.current_thread()) # 显示所有线程名和id print(threading.enumerate())
守护线程
#守护进程随着主线程程代码的执行结束而结束。
#守护线程会在主线程执行完之后等待其他子线程的结束才结束。
#主线程在执行完自己的代码之后不会立即结束 而是等待子线程结束之后 回收子线程的资源。
import time from threading import Thread def func1(): while 1 : time.sleep(1) print("\033[31m ******我还活着呢\033[0m") def func2(): time.sleep(10) print("我他吗是 func2") if __name__ =='__main__': t1 = Thread(target=func1) # 定义一个守护线程(主线程结束之后 等待其他子线程的结束才结束 守护线程随之结束) t1.daemon = True t1.start() t2 = Thread(target=func2) t2.start() print("主线程")
线程锁(互斥锁)
数据不安全问题:
#10个线程同时开起来 同时去拿n = 10,拿回来之后隔了0.2秒才回来。
#在拿回来的过程当中别人都去拿,都拿的10,赋值回去了就是9
from threading import Lock, Thread import time # 死锁问题 def func(): global n temp = n time.sleep(0.1) n = temp - 1 n = 10 lst = [] for i in range(10): t = Thread(target=func, args=()) t.start() lst.append(t) # 等待子线程执行完毕之后我再执行 t.join() for i in lst: print(n)
0.2秒钟做的事情
解决数据不安全问题
加锁
from threading import Lock from threading import Thread import time # 死锁问题 def func(lock): global n # 拿钥匙 保证数据安全 lock.acquire() temp = n time.sleep(0.1) n = temp - 1 # 还钥匙 保证数据安全 lock.release() n = 10 lst = [] lock = Lock() for i in range(10): t = Thread(target=func, args=(lock,)) t.start() lst.append(t) # 等待子线程执行完毕之后我再执行 t.join() for i in lst: print(n)
科学家吃面现象(死锁问题)
只有一把钥匙,如果你要是同时,不管在一个进程里,还是在多个进程之间,你想拿多个钥匙就不行了。
from threading import Lock from threading import Thread import time # 定义一个面条锁 noodle_lock = Lock() # 定义一个叉子锁 fork_lock = Lock() def eat1(name): # 加面条锁 noodle_lock.acquire() print("\033[31m %s 拿到面条了\033[0m" % name) # 加勺子锁 fork_lock.acquire() print('%s 拿到叉子了' % name) print('%s 吃面' % name) # 释放勺子锁 fork_lock.release() # 释放面条锁 noodle_lock.release() def eat2(name): # 加勺子锁 fork_lock.acquire() print('%s 拿到叉子了' % name) # 在停顿的时候黄埔也过去拿了面条,由于没有钥匙了 所以就停住了 time.sleep(1) # 加面条锁 noodle_lock.acquire() print("\033[31m %s 拿到面条了\033[0m" % name) print('%s 吃面' % name) # 释放勺子锁 fork_lock.release() # 释放面条锁 noodle_lock.release() Thread(target=eat1, args=('Riven',)).start() Thread(target=eat2, args=('Mark',)).start() Thread(target=eat1, args=('黄埔',)).start() Thread(target=eat2, args=('汨汨',)).start()
解决死锁问题(递归锁)
同一个线程里拿多少次钥匙都可以,但又一个人拿到了这一串钥匙别的人就再也拿不到了。
from threading import RLock # RLock = 一串钥匙 rlock = RLock() rlock.acquire() rlock.acquire() rlock.acquire() rlock.acquire() rlock.acquire() rlock.acquire() rlock.acquire() rlock.acquire() rlock.acquire() print('123')
from threading import Thread from threading import RLock import time # 一个钥匙串 2 把钥匙 fork_lock = noodle_lock = RLock() def eat1(name): # 我拿了一把钥匙,就一串钥匙在我手上 noodle_lock.acquire() print("\033[31m %s 拿到面条了\033[0m" % name) fork_lock.acquire() print('%s 拿到叉子了' % name) print('%s 吃面' % name) # 等我把这一串钥匙都还了,下个人才能进来 就不会出现阻塞现象 fork_lock.release() # 等我把这一串钥匙都还了,下个人才能进来 就不会出现阻塞现象 noodle_lock.release() def eat2(name): # # 我拿了一把钥匙,就一串钥匙在我手上 fork_lock.acquire() print('%s 拿到叉子了' % name) time.sleep(1) noodle_lock.acquire() print("\033[31m %s 拿到面条了\033[0m" % name) print('%s 吃面' % name) # 等我把这一串钥匙都还了,下个人才能进来 就不会出现阻塞现象 fork_lock.release() # 等我把这一串钥匙都还了,下个人才能进来 就不会出现阻塞现象 noodle_lock.release() Thread(target=eat1, args=('Riven',)).start() Thread(target=eat2, args=('Mark',)).start() Thread(target=eat1, args=('黄埔',)).start() Thread(target=eat2, args=('汨汨',)).start()
信号量(Semaphore)
事件
False状态
当Wait() false时阻塞
当Wait() ture时非阻塞
Clear False状态修改为False
Set False状态修改为True
例子
(连接数据库,检测数据库的可连接情况)
数据库---文件夹:
1.能够更方便的对数据进行增删改查
2.安全访问的机制
条件(Condition)
一个条件被创建之初默认有一个False状态。
False 状态会影响wait一直处于等待状态。
notify(int数据类型)制造几把钥匙。有几把钥匙就执行几次
from threading import Thread from threading import Condition def func(con, i): con.acquire() # 等钥匙,也就是说你有几把钥匙,就执行几次 con.wait() print("\033[31m 在第 %s 个循环里\033[0m" % i) con.release() con = Condition() for i in range(10): Thread(target=func, args=(con, i)).start() while 1: num = int(input('>>>>')) con.acquire() con.notify(num) # 造钥匙 con.release()
线程定时器(Timer)
import time from threading import Timer def func(): print('时间同步') while True: t = Timer(5, func).start() # 需要定义一个延时时间 time.sleep(3)
队列
# 进程队列 先进先出
import queue # 进程队列 先进先出 q = queue.Queue() # 先进先出 # q.put(1) # q.put(2) q.put_nowait(1) q.put_nowait(2) # get_nowait 不会阻塞 会抛错 print(q.get_nowait()) print(q.get_nowait()) print(q.get_nowait()) # get 会阻塞 # print(q.get()) # print(q.get())
栈 先进后出
import queue # 栈 先进后出 q = queue.LifoQueue() q.put(1) q.put(2) q.put(3) print(q.get()) print(q.get()) print(q.get()) print(q.get())
优先级队列(按照值的大小进行排序 从小到大)
import queue # 优先级队列(按照值的大小进行排序 从小到大) q = queue.PriorityQueue() q.put(20) q.put(50) q.put(25) q.put(40) print(q.get()) print(q.get()) print(q.get()) print(q.get())
线程池(ThreadPoolExecutor)
import time from concurrent.futures import ThreadPoolExecutor def func(n): print(n) time.sleep(1) return n * 10 t_lst = [] # 定义一个线程池(默认 不要超过cup个数*5) tpool = ThreadPoolExecutor(max_workers=5) for i in range(20): # 传值(开启20个子线程) t = tpool.submit(func, i) t_lst.append(t) # 相当于 close + join tpool.shutdown() print("主线程") for t in t_lst: # t.result() 接受返回值 print("\033[31m ==== \033[0m", t.result())
如果接受不到 返回值
在自定义函数中接受返回值
原文地址:https://www.cnblogs.com/Rivend/p/12040470.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 面试进阶-数据库中需要理解的锁
- 剑指offer第9题:旋转数组的最小数字
- Mysql的SQL性能优化指北
- H3C 配置管理实验
- 融入ThingJS 3D可视化方案,让城市管线更加智能、高效
- 类加载机制浅记
- 聊聊dubbo-go的nacosRegistry
- Java离Linux内核有多远?
- 关于懒汉模式和恶汉模式的区别
- Chrome 新功能 — CSS Overview 尝鲜
- 0门槛,轻松实现条形竞赛图动画
- 读懂数据库中的乐观锁和悲观锁和MVCC
- CentOS 7.x安装微服务网关Apache APISIX
- Sentinel规则Pull模式持久化
- 如何用Cloudbase Framework部署一个Vue项目?