-xubuntu、anaconda、pycharm、python3.7
-https://www.cnblogs.com/jokerbj/p/7460260.html
-https://www.dabeaz.com/python/UnderstandingGIL.pdf
-程序:一堆代码以文本形式存入一个文档
-进程:程序运行的一个状态
-包含地址空间、内存数据线等
-每个进程有自己完全独立的运行环境,多进程共享数据是一个问题
-线程
-一个进程的独立运行片段,一个进程可以有多个线程
-轻量化的进程
-一个进程的多个线程间共享数据和上下文运行环境
-共享互斥问题
-全局解释器锁(GIL)
-Python代码的执行是由python虚拟机进行控制
-在主循环中只能有一个控制线程在执行
-Python包
-thread:有问题,不好用,python3改成了_thread
-threading:通行的包
-案例:第一个:顺序执行,耗时长;
第二个:多线程,耗时短
第三个:多线程,传参数
'''
利用time函数,生成两个函数
程序调用
计算总的运行时间
'''
import time
def loop1():
#ctime 得到当前时间
print('Start loop1 at:',time.ctime())
#睡眠多长时间,单位是秒
time.sleep(4)
print('End loop1 at:',time.ctime())
def loop2():
#ctime 得到当前时间
print('Start loop2 at:',time.ctime())
#睡眠多长时间,单位是秒
time.sleep(2)
print('End loop2 at:',time.ctime())
def main():
print("Sarting at:",time.ctime())
loop1()
loop2()
print("All done at:",time.ctime())
if __name__=='__main__':
main()
运行:
Sarting at: Sun Mar 31 10:26:00 2019
Start loop1 at: Sun Mar 31 10:26:00 2019
End loop1 at: Sun Mar 31 10:26:04 2019
Start loop2 at: Sun Mar 31 10:26:04 2019
End loop2 at: Sun Mar 31 10:26:06 2019
All done at: Sun Mar 31 10:26:06 2019
-----------------------------------------------------------
'''
多线程
'''
import time
import _thread as thread
def loop1():
#ctime 得到当前时间
print('Start loop1 at:',time.ctime())
#睡眠多长时间,单位是秒
time.sleep(4)
print('End loop1 at:',time.ctime())
def loop2():
#ctime 得到当前时间
print('Start loop2 at:',time.ctime())
#睡眠多长时间,单位是秒
time.sleep(2)
print('End loop2 at:',time.ctime())
#有三个线程,一个主线程(主管),两个工作的人,干的活是loop1、loop2
def main():
print("Sarting at:",time.ctime())
#启动多线程的意思是用多线程去执行某个函数
#启动多线程函数为start_new_thread
#参数两个,一个是需要运行的函数名,第二个函数参数作为元组使用
#注意:如果函数只有一个参数,需要参数后有一个括号,若有参数放在括号里
thread.start_new_thread(loop1,())
thread.start_new_thread(loop2,())
print("All done at:",time.ctime())
if __name__=='__main__':
main()
#死循环,主线程一直等
while True:
time.sleep(1)
运行:
Sarting at: Sun Mar 31 10:54:45 2019
All done at: Sun Mar 31 10:54:45 2019
Start loop2 at:Start loop1 at: Sun Mar 31 10:54:45 2019Sun Mar 31 10:54:45 2019
End loop2 at: Sun Mar 31 10:54:47 2019
End loop1 at: Sun Mar 31 10:54:49 2019
-----------------------------------------------------------------------------------
'''
利用time延时函数生成两个函数
利用多线程调用
计算总运行时间
练习带参数的多线程启动方法
'''
import time
#导入多线程包并更名为thread
import _thread as thread
def loop1(in1):
print('Start loop1 at:',time.ctime())
#把参数打印出来
print("我是参数",in1)
#睡眠多长时间,单位是秒
time.sleep(4)
print('End loop1 at : ',time.ctime())
def loop2(in1,in2):
print('Start loop2 at:',time.ctime())
#把参数打印出来,代表使用
print("我是参数",in1,"和参数",in2)
#睡眠多长时间,单位是秒
time.sleep(2)
print('End loop1 at : ',time.ctime())
def main():
print("Sarting at:",time.ctime())
thread.start_new_thread(loop1,("haha",))
thread.start_new_thread(loop2,("kaka","lala"))
print("All done at:",time.ctime())
if __name__=='__main__':
main()
#一定要有while语句
#因为启动多线程后本程序就被作为主线程存在
#如果主线程执行完毕,则子线程可能也需要终止
while True:
time.sleep(10)
运行:
Sarting at: Sun Mar 31 11:16:04 2019
All done at: Sun Mar 31 11:16:04 2019
Start loop2 at:Start loop1 at: Sun Mar 31 11:16:04 2019Sun Mar 31 11:16:04 2019
我是参数我是参数 kakahaha 和参数
lala
End loop1 at : Sun Mar 31 11:16:06 2019
End loop1 at : Sun Mar 31 11:16:08 2019
-threading的使用
-直接利用threading.Thread生成Thread实例
- t = threading.Thread(target=xxx,args=(xxx,))
- t.start():启动多线程
-t.join():等待多线程执行完成
import time
import threading
def loop1(in1):
print('Start loop1 at:',time.ctime())
#把参数打印出来
print("我是参数",in1)
#睡眠多长时间,单位是秒
time.sleep(4)
print('End loop1 at : ',time.ctime())
def loop2(in1,in2):
print('Start loop2 at:',time.ctime())
print("我是参数",in1,"和参数",in2)
time.sleep(2)
print('End loop1 at : ',time.ctime())
def main():
print("Sarting at:",time.ctime())
#生成threading.Thread实例
t1 = threading.Thread(target=loop1,args=("haha",))
t1.start()
t2 = threading.Thread(target=loop2,args=("kaka","lala"))
t2.start()
#加入join,让“All done at垫底”
t1.join()
t2.join()
print("All done at:",time.ctime())
if __name__=='__main__':
main()
while True:
time.sleep(10)
运行结果:
Sarting at: Sun Mar 31 16:33:06 2019
Start loop1 at: Sun Mar 31 16:33:06 2019
我是参数 haha
Start loop2 at: Sun Mar 31 16:33:06 2019
我是参数 kaka 和参数 lala
End loop1 at : Sun Mar 31 16:33:08 2019
End loop1 at : Sun Mar 31 16:33:10 2019
All done at: Sun Mar 31 16:33:10 2019
-守护线程 daemon 我要和主线程共存亡!!!
-如果在程序中将子线程设置成守护线程,则子线程会在主线程结束时自动退出
-一般认为,守护线程不重要或者不允许离开主线程独立运行
-守护线程案例能否有效果跟环境相关
-案例:非守护/守护
#非守护
import time
import threading
def fun():
print("Start fun")
time.sleep(2)
print("end fun")
print("Main thread")
t1 = threading.Thread(target=fun,args=())
t1.start()
time.sleep(1)
print("Main thread end")
运行结果:
Main thread
Start fun
Main thread end
end fun
------------------------------------------------------------------
#守护
import time
import threading
def fun():
print("Start fun")
time.sleep(2)
print("end fun")
print("Main thread")
t1 = threading.Thread(target=fun,args=())
#设置守护线程的方法,必须在start之前设置,否则无效
#t1.deamon = True
t1.setDaemon(True)
t1.start()
time.sleep(1)
print("Main thread end")
运行结果:
Main thread
Start fun
Main thread end
-线程常用属性
-threading.currentThread:返回当前线程变量
-threading.enumerate:返回一个包含正在运行的线程的list,正在运行的线程指线程启动后、结束前
-threading.activeCount:返回正在运行的线程数量,效果跟len(tghreading.enumerate)相同
-thr.setName:给线程设置名字
-thr.getName:得到线程的名字
import time,threading
#导入多线程包并更名为thread
import _thread as thread
def loop1():
print('Start loop1 at:',time.ctime())
#睡眠多长时间,单位是秒
time.sleep(3)
print('End loop1 at : ',time.ctime())
def loop2():
print('Start loop2 at:',time.ctime())
time.sleep(2)
print('End loop1 at : ',time.ctime())
def loop3():
print('Start loop3 at:', time.ctime())
time.sleep(5)
print('End loop3 at : ', time.ctime())
def main():
print("Starting at: ",time.ctime())
t1 = threading.Thread(target=loop1,args=())
t1.setName("Thr_1")
t1.start()
t2 = threading.Thread(target=loop2, args=())
t2.setName("Thr_2")
t2.start()
t3 = threading.Thread(target=loop3, args=())
t3.setName("Thr_3")
t3.start()
#预计3秒后thread2已经自动结束
time.sleep(3)
#enumerate 得到正在运行子线程,即子线程1和子线程3
for thr in threading.enumerate():
#getName能够得到线程的名字
print("正在运行的线程名字是:{0}".format(thr.getName()))
print("正在运行的子线程数量为:{0}".format(threading.activeCount()))
print("All done at:",time.ctime())
if __name__=="__main__":
main()
while True:
time.sleep(10)
运行结果:
Starting at: Sun Mar 31 17:35:38 2019
Start loop1 at: Sun Mar 31 17:35:38 2019
Start loop2 at: Sun Mar 31 17:35:38 2019
Start loop3 at: Sun Mar 31 17:35:38 2019
End loop1 at : Sun Mar 31 17:35:40 2019
正在运行的线程名字是:MainThread
正在运行的线程名字是:Thr_1
正在运行的线程名字是:Thr_3
正在运行的子线程数量为:3
All done at: Sun Mar 31 17:35:41 2019
End loop1 at : Sun Mar 31 17:35:41 2019
End loop3 at : Sun Mar 31 17:35:43 2019
-直接继承自threading.Thread
-直接继承Thread,重写run函数,类实例可以直接运行
import time
import threading
#1、类需要继承自threading.Thread
class MyThread(threading.Thread):
def __init__(self,arg):
super(MyThread, self).__init__()
self.arg= arg
#2、必须重写run函数,run函数代表的是真正执行的功能
def run(self):
time.sleep(2)
print("the args for this class is {0}".format(self,arg))
for i in range(5):
t = MyThread(i)
t.start()
t.join()
print("Main thread is done!!!")
企业版喜欢这么写:
import time
import threading
loop = [4,2]
class ThreadFunc:
def __init__(self,name):
self.name = name
def loop(self,nloop,nsec):
'''
:param nloop:
:param nsec:
:return:
'''
print('Start loop', nloop,'at', time.ctime())
time.sleep(nsec)
print("Done loop", nloop,'at', time.ctime())
def main():
print("Starting at:",time.ctime())
'''ThreadFunc('loop').loop 跟以下两个式子相等
t = ThreadFunc('loop')
t.loop
'''
#以下t1和t2定义方式相等
t = ThreadFunc("loop")
t1 = threading.Thread(target=t.loop,args=("Loop1",4))
#下面这种写法更西方人,工业化一点
t2 = threading.Thread(target=ThreadFunc("loop").loop,args=("loop",2))
#常见的错误写法
#t1 = threadingThread(target=ThreadFunc("loop").loop(100,4))
t1.start()
t2.start()
t1.join()
t2.join()
print("All done at: ",time.ctime())
if __name__ == '__main__':
main()
运行:
Starting at: Mon Apr 1 09:48:54 2019
Start loop Loop1 at Mon Apr 1 09:48:54 2019
Start loop loop at Mon Apr 1 09:48:54 2019
Done loop loop at Mon Apr 1 09:48:56 2019
Done loop Loop1 at Mon Apr 1 09:48:58 2019
All done at: Mon Apr 1 09:48:58 2019
-共享变量:当多个线程同时访问一个变量的时候,会产生共享变量的问题
-解决变量:锁、信号灯
-锁(Lock):
-是一个标志,表示一个线程在占用一些资源
-使用方法:
-上锁
-使用共享资源,放心地用
-取消锁,释放锁
-锁谁:哪个资源需要多个线程共享,锁哪个,锁其实不是锁住谁,是一个令牌
-线程安全问题:
-如果一个资源/变量,他对于线程来讲,不用加锁也不会引起任何问题
-线程不安全变量类型:list、set、dict
-线程安全变量类型:queue
-生产者消费者问题
-一个模型,可以用来搭建消息队列
-queue是一个用来存放变量的数据结构,特点是先进先出,内部元素排队
import threading,time
#python2 from Queue import Queue
#python3
import queue
class Producer(threading.Thread):
def run(self):
global queue
count = 0
while True:
#qsize返回queue内部长度
if queue.qsize() < 1000:
for i in range(100):
count += 1
msg = '生成产量'+str(count)
#put是往queue中放入
queue.put(msg)
print(msg)
time.sleep(0.5)
class Consumer(threading.Thread):
def run(self):
global queue
while True:
if queue.qsize() > 100:
for i in range(3):
#get从queue中取出一个值
msg = self.name + "消费了"+queue.get()
print(msg)
time.sleep(1)
if __name__ == '__main__':
queue = queue.Queue()
for i in range(500):
queue.put("初始产品"+str(i))
for i in range(2):
p = Producer()
p.start()
for i in range(5):
c = Consumer()
c.start()
-死锁问题
-锁的等待时间问题
import threading,time
lock_1 = threading.Lock()
lock_2 = threading.Lock()
def func_1():
print("func_1 starting...")
lock_1.acquire(timeout=4)
print("func_1 申请了lock_1...")
time.sleep(2)
print("lock_1等待lock_2")
rst = lock_2.acquire(timeout=2)
#申请锁是否成功
if rst:
print("func_1已经得到锁lock_2")
lock_2.release()
print("func_1释放了Lock_2...")
else:
print("func_1释放了lock_2")
lock_1.release()
print("func_1释放了lock_1")
print("func_1 done...")
def func_2():
print("func_2 starting...")
lock_2.acquire()
print("func_2 申请了lock_2...")
time.sleep(4)
print("lock_2等待lock_1")
lock_1.acquire()
print("func_2释放了Lock_1...")
lock_1.release()
print("func_2释放了lock_1")
lock_2.release()
print("func_2释放了lock_2")
print("func_2 done...")
if __name__ == '__main__':
print("主程序启动...")
t1 = threading.Thread(target=func_1,args=())
t2 = threading.Thread(target=func_2,args=())
t1.start()
t2.start()
t1.join()
t2.join()
print("主程序启动...")
运行:
主程序启动...
func_1 starting...
func_1 申请了lock_1...
func_2 starting...
func_2 申请了lock_2...
lock_1等待lock_2
func_1释放了lock_2
func_1释放了lock_1
func_1 done...
lock_2等待lock_1
func_2释放了Lock_1...
func_2释放了lock_1
func_2释放了lock_2
func_2 done...
主程序启动...
-semaphore:允许一个资源最多由几个多线程同时使用
import threading,time
#参数定义最多几个线程同时使用资源
semaphore = threading.Semaphore(3)
def func():
if semaphore.acquire():
for i in range(5):
print(threading.currentThread().getName() + "get semaphore")
time.sleep(15)
semaphore.release()
print(threading.currentThread().getName() + "release semaphore")
for i in range(8):
t1 = threading.Thread(target=func)
t1.start()
-threading.Timer
import threading,time
def func():
print(" I am running...")
time.sleep(4)
print("I am done....")
if __name__ == '__main__':
#Timer的作用:六秒之后调用func
t = threading.Timer(6,func)
t.start()
i = 0
while True:
print("{0}**************".format(i))
time.sleep(3)
i += 1
-可重入锁
-一个锁,可以被一个线程多次申请
-主要解决递归调用的时候,需要申请锁的情况
import threading,time
class MyThread(threading.Thread):
def run(self):
global num
time.sleep(1)
if mutex.acquire(1):
num += 1
msg = self.name+'set num to'+str(num)
print(msg)
mutex.acquire()
mutex.release()
mutex.release()
num = 0
#mutex = threading.Lock()
mutex = threading.RLock()
def testTh():
for i in range(5):
t = MyThread()
t.start()
if __name__ == '__main__':
testTh()
运行:
Thread-5set num to1
Thread-4set num to2
Thread-3set num to3
Thread-2set num to4
Thread-1set num to5