threading多线程模块
1 基本实现
Thread(target=函数名,args=(以元组形式传递的实参,要加","))
th = threading.Thread(target=run,args=(i,))就是实例化一个线程
th.start()就是对实例调用启动函数。
在内部,主线程就会创建30个子线程,子线程并发执行,所以虽然每个线程sleep(3),但是是并发执行的。
进程总耗时3s出头。
import time
import threading
def run(arg):
print('run %s' %(arg))
time.sleep(3) for i in range(30):
th = threading.Thread(target=run,args=(i,))
th.start()
2 深入理解线程
2.1 主线程和子线程
程序执行时,产生一个进程,进程里首先有一个主线程,每个执行的是子线程
使用threading.current_thread(),发现在for循环中是主线程,在run函数里是子线程。
import time
import threading
def run(arg):
print('run %s' %(arg))
time.sleep(3) for i in range(3):
th = threading.Thread(target=run,args=(i,))
print(threading.current_thread())
th.start()
>>>>
<_MainThread(MainThread, started 13112)>
run 0
<_MainThread(MainThread, started 13112)>
run 1
<_MainThread(MainThread, started 13112)>
run 2
import time
import threading
def run(arg):
print('run %s' %(arg))
print(threading.current_thread())
time.sleep(3) for i in range(3):
th = threading.Thread(target=run,args=(i,))
th.start()
>>>>
run 0
<Thread(Thread-1, started 9976)>
run 1
<Thread(Thread-2, started 9980)>
run 2
<Thread(Thread-3, started 10800)>
2.2 子线程的并发性
cost_time的打印值:cost time 0.07500743865966797
发现没有在上面的for循环结束后再执行cost_time = time.time() - start_time语句。
因为每个实例化线程就是创建子线程,创建完后子线程自己去运行。主线程马上进入下一个执行语句,不会等待子线程执行完毕。
import time
import threading
def run(arg):
print('run %s' %(arg))
time.sleep(10) start_time = time.time() for i in range(600):
th = threading.Thread(target=run,args=(i,))
th.start() cost_time = time.time() - start_time
print('cost time', (cost_time))
3 JOIN()
就是wait函数,一个线程调用join(),主线程就会等子线程执行完毕再往下走.
在这个程序中,相当于线程单并发顺序执行。
import time
import threading
def run(arg):
print('run %s' %(arg))
time.sleep(1) start_time = time.time() for i in range(10):
th = threading.Thread(target=run,args=(i,))
th.start()
th.join() cost_time = time.time() - start_time
print('cost time', (cost_time))
>>>
E:\Python\2018L1\venv\Scripts\python.exe E:/Python/2018L1/test/threadingserver.py
run 0
run 1
run 2
run 3
run 4
run 5
run 6
run 7
run 8
run 9
cost time 10.010000944137573
创建空列表t_list,然后把线程实例作为元素追加到列表(不在这里写join,不然会在每个线程中顺序sleep。)
在一个for循环里,让每个实例执行join()。
最后cost time 3.002300262451172
import time
import threading
def run(arg):
print('run %s' %(arg))
time.sleep(3) start_time = time.time()
t_list = []
for i in range(10):
th = threading.Thread(target=run,args=(i,))
th.start()
t_list.append(th) for i in t_list:
i.join() cost_time = time.time() - start_time
print('cost time', (cost_time))
4 setDaemon
当主线程退出,守护子线程不管有没有执行完毕,都会马上退出。
对于非守护子线程,主线程会等它执行完毕再退出。
对于守护线程,主线程不会等它执行完毕,而是直接退出。
4.1
以下程序,虽然没有join函数,但主线程也会在所有线程执行完毕后才退出。
import time
import threading
def run(arg):
print('run %s' %(arg))
time.sleep(3)
print(threading.current_thread()) for i in range(3):
th = threading.Thread(target=run,args=(i,))
#th.setDaemon(True)
th.start()

4.2
如果把子线程都设置为守护线程,就是说主线程不会在它执行完毕再退出,而是直接退出。
print(threading.current_thread())还没执行,就已经退出,不会再执行
import time
import threading
def run(arg):
print('run %s' %(arg))
time.sleep(3)
print(threading.current_thread()) for i in range(3):
th = threading.Thread(target=run,args=(i,))
th.setDaemon(True)
th.start()
4.3
主线程的执行时间比守护子线程长。在主线程退出前子线程已执行完毕。
import time
import threading
def run(arg):
print('run %s' %(arg))
time.sleep(3)
print(threading.current_thread()) for i in range(3):
th = threading.Thread(target=run,args=(i,))
th.setDaemon(True)
th.start()
time.sleep(4)
5 GIL全局解释器锁
在cpython上,使用gil(global interpreter lock),来保证同一时间只有一个线程在解释器中运行。所有的线程并发都是通过context switch来完成。
这使得python无法真正使用多核cpu。
6 线程锁(互斥锁)
6.1 线程共享数据池
在进程中的多线程,共享进程的内存空间。就是可以对同一个数据进行操作
import time
import threading
num = 0
def run():
global num #函数使用全局变量,需要global声明
time.sleep(2)
num += 1
print('thread:',num)
for i in range(20):
th = threading.Thread(target=run)
th.start()
time.sleep(5)
print(num)
6.2 线程锁的作用
多个线程同时操作同一块数据,假设t1先拿到data = 0,然后使用解释器,调用cpu运算 data ++。还没运算完成,就被context switch。
这时t2也操作data,这是data = 0,然后使用解释器,调用cpu运算data ++,然后把data = 1写入data数据。
这时切换回t1,t1从context里拿到数据data = 0,运算完成,然后把data = 1写入data数据。
这样就出错了。
所以需要对data这块数据上锁,同一时间只能有一个线程进行操作。
python3上程序会自动加锁。
6.3 死锁和递归锁
https://blog.csdn.net/u013210620/article/details/78723704
用得着再看
6.4 信号量
同一时间有几个线程可以访问共享数据。
信号量就是多把锁,允许同时多个线程运行。
可以控制同一时刻可以运行的线程数。
7 Event事件
用于实现线程间通信
set表示设定标志位,clear是清空标志位,在处理标志位的函数体中
wait是等待标志位为set,is_set是判断标志位是否为set,在检测标志位的函数体中
import time
import threading event = threading.Event() #-----红绿灯函数,在红灯时标志位清零,绿灯设置标志位-----
def lighter():
count = 0
event.set()
while True:
count += 1
time.sleep(1)
if count > 20 and count <= 30:
event.clear() #20-30s,红灯
print('\33[41mred light on\33[0m')
elif count > 30:
event.set()
count = 0
else:
print('\33[42mgreen light on\33[0m') #----汽车函数,红灯停绿灯行,每秒1km----
def car(name):
global mileage
while True:
if event.is_set():
mileage += 1
time.sleep(1)
print('%s is running,the mileage is %s kilometer' % (name,mileage))
else:
time.sleep(1)
print('%s is wait' %(name))
event.wait() #等待标志位设为set if __name__ == '__main__':
mileage = 0 car1 = threading.Thread(target=car,args=('本田车',))
car1.start()
light = threading.Thread(target=lighter,)
light.start()
8 应用场景
python是伪多线程,实际上是单线程在context switch,所以不适合cpu密集型操作任务,而适合io密集型任务。(socket的多并发网络连接就是io密集型任务)
threading多线程模块的更多相关文章
- python笔记9 线程进程  threading多线程模块  GIL锁  multiprocessing多进程模块 同步锁Lock   队列queue  IO模型
		线程与进程 进程 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成.我们编写的程序用来描述进程要完成哪些功能以及如何完成:数据集则是程序在执行过程中所需要 ... 
- python-网络安全编程第六天(threading多线程模块&Queue模块&subprocess模块)
		前言 昨天晚上9点多就睡了 2点起来没睡意... 那就学习吧emmmm ,拿起闲置几天的python课程学习.学习到现在5.58了 总结下 继续开始学习新的内容 多多线程? 线程(英语:thread) ... 
- python:threading多线程模块-创建线程
		创建线程的两种方法: 1,直接调用threading.Thread来构造thread对象,Thread的参数如下: class threading.Thread(group=None, target= ... 
- python——Tkinter图形化界面及threading多线程
		Tkinter模块("Tk 接口")是Python的标准Tk GUI工具包的接口.Tk和Tkinter可以在大多数的Unix平台下使用,同样可以应用在Windows和Macinto ... 
- 基于Python的多线程模块Threading小结
		步入正题前,先准备下基本知识,线程与进程的概念. 相信作为一个测试人员,如果从理论概念上来说其两者的概念或者区别,估计只会一脸蒙蔽,这里就举个例子来说明下其中的相关概念. 平安夜刚过,你是吃到了苹果还 ... 
- Python多线程模块
		引言 thread threading 1 Thread 11 下面使用threading模块实现与上面相同的功能 12 在创建新线程时还可以给Thread传递可调用类的对象这样使用类本身来保存信息 ... 
- 用生动的案例一步步带你学会python多线程模块
		鱼和熊掌不可兼得 鱼,我所欲也,熊掌,亦我所欲也,二者不可得兼,舍鱼而取熊掌者也. 从6月开始写公众号,连着四个月一直尽量保证一周五更,结果整天熬夜搞的身体素质骤降.十一休假决定暂时将公众号放放,好好 ... 
- 多线程模块的同步机制event对象
		多线程模块的同步机制event对象 线程的核心特征就是他们能够以非确定的方式(即何时开始执行,何时被打断,何时恢复完全由操作系统来调度管理,这是用户和程序员无法确定的)独立执行的,如果程序中有其他线程 ... 
- Perl 多线程模块 Parallel::ForkManager
		Perl 多线程模块 Parallel::ForkManager 一个简单的并行处理模块.这个是用来对付循环的多线程处理. 放在循环前面. Table of Contents 1 Synops内容简介 ... 
随机推荐
- lodar
			一个文件使用另一个文件的东西的时候需要使用到 export{开放} --watch 自动检测 可以加载打包的后边 module.exports = { entry:{ //入口文件 home:&quo ... 
- 记录魅族m1note编译TWRP recovery 3.1.0-0,包括mtk机型的处理方法
			1.安装64位linux系统,我用的是deepin os 15.3 2.将系统升级到最新版本 sudo apt-get update && sudo apt-get upgrade 3 ... 
- Linux MySQL主从复制(Replication)配置
			MySQL是开源的关系型数据库系统.复制(Replication)是从一台MySQL数据库服务器(主服务器master)复制数据到另一个服务器(从服务器slave)的一个进程. 配置主服务器(mast ... 
- RecyclerView(替代ListView)使用方法介绍
			在build.gradle文件加入以下代码 compile 'com.android.support:cardview-v7:21.0.3' compile 'com.android.support: ... 
- 【网络协议】IP协议、ARP协议、RARP协议
			IP数据报 IP是TCP/IP协议族中最核心的协议,全部的TCP.UDP.ICMP.IGMP数据都以IP数据报的格式传输.IP仅提供尽力而为的传输服务.假设发生某种错误.IP会丢失该数据.然后发送IC ... 
- Ajax的简单实现
			Ajax的实现需要服务器端和客户端配合来实现 下面看服务器端的代码,也就是用php编写的一个后台脚本文件 <?php //设置页面内容,编码格式是utf8 header("Conten ... 
- var  let  Hositing  const  Temporal Dead Zone
			var let Hositing const Temporal Dead Zone 临时死区 
- HDFS运维和优化
			常见问题 下面列举HDFS运行过程中可能出现的常见问题及解决方法,这些问题一般都会在日志中出现的相应的记录.Incompatible clusterIDs in … :namenode cluster ... 
- vim使用手册出现    找到 tag:1/9或更多 查看别的定义的方法
			:ts 或 tselect 查看有相同地方的定义 通过这种方式会出现一个列表,输入:q 然后通过数字键和回车查看某一个定义,个人经常用:ts :tn或tnext 查找下一个定义地方. :tp 查找上一 ... 
- android之View坐标系(view获取自身坐标的方法和点击事件中坐标的获取)
			在做一个view背景特效的时候被坐标的各个获取方法搞晕了,几篇抄来抄去的博客也没弄很清楚. 现在把整个总结一下. 其实只要把下面这张图看明白就没问题了. 涉及到的方法一共有下面几个: view获取自身 ... 
