###多线程
-https://www.cnblogs.com/jokerbj/p/7460260.html
-http://www.dabeaz.com/python/UnderstandingGIL.pdf
# 多线程 vs 多进程
-程序:一堆代码以文本形式存入一个文档
-进程:程序运行的一个状态
-包含地址空间、内存、数据栈等
-每个进程有自己完全独立的运行环境,多进程共享数据是一个问题
-线程:
-一个进程就是独立运行片段,一个进程可以有多个线程
-轻量化的进程
-一个进程的多个线程间共享数据和上下文运行环境
-共享互斥问题
-全局解释器锁(GIL)
-Python代码的执行是由Python虚拟机进行控制
-在主循环中只能有一个控制线程在执行
-Python包
-thread包:有问题,不好用,python3改成了_thread
-threading:通行的包
-案例01:顺序执行,耗时比较长
'''
利用time函数,生成两个函数
顺序调用
计算总的运行时间
'''
import time
def loop1():
#ctime得到当前时间
print('Start loop 1 at :', time.ctime())
#睡眠多长时间,单位是秒
time.sleep(4)
print('End loop 1 at :', time.ctime())
def loop2():
#ctime得到当前时间
print('Start loop 2 at:', time.ctime())
#睡眠多长时间,单位是秒
time.sleep(2)
print('End loop 2 at:', time.ctime())
def main():
print("Starting at:", time.ctime())
loop1()
loop2()
print('All done at:', time.ctime())
if __name__ == "__main__":
main()
-案例02:案例01的另外一个不被推荐的改变(调用_thread包)
改用多线程,缩短总时间,使用_thread
'''
利用time函数,生成两个函数
顺序调用
计算总的运行时间
'''
import time
import _thread as thread
def loop1():
#ctime得到当前时间
print('Start loop 1 at :', time.ctime())
#睡眠多长时间,单位是秒
time.sleep(4)
print('End loop 1 at :', time.ctime())
def loop2():
#ctime得到当前时间
print('Start loop 2 at:', time.ctime())
#睡眠多长时间,单位是秒
time.sleep(2)
print('End loop 2 at:', time.ctime())
def main():
print("Starting at:", time.ctime())
#启动多线程的意思是用多线程去执行某个函数
#启动多线程函数为start_new_thead
#参数两个,一个是需要运行的函数名,第二是函数的参数作为元组使用,为空则使用空元祖
#注意:如果函数只有一个参数,那么后面需要一个逗号
thread.start_new_thread(loop1, ())
thread.start_new_thread(loop2, ())
print('All done at:', time.ctime())
if __name__ == "__main__":
main()
-案例03:多线程,传参数
'''
利用time函数,生成两个函数
利用多线程调用
计算总的运行时间
练习带参数的多线程启动方法
'''
import time
import _thread as thread
def loop1(in1):
#ctime得到当前时间
print('Start loop 1 at:', time.ctime())
#把参数打印出来
print("我是参数", in1)
#睡眠多长时间,单位是秒
time.sleep(4)
print('End loop 1 at:', time.ctime())
def loop2(in1, in2):
#ctime得到当前时间
print('Start loop 2 at:', time.ctime())
#把参数打印出来
print("我是参数", in1, "和参数", in2)
#睡眠多长时间,单位是秒
time.sleep(2)
print('End loop 2 at:', time.ctime())
def main():
print("Starting at:", time.ctime())
#启动多线程的意思是用多线程去执行某个函数
#启动多线程函数为start_new_thead
#参数两个,一个是需要运行的函数名,第二是函数的参数作为元组使用,为空则使用空元祖
#注意:如果函数只有一个参数,那么后面需要一个逗号
thread.start_new_thread(loop1, ("刘亦菲1",))
thread.start_new_thread(loop2, ("刘亦菲2","刘亦菲3"))
print('All done at:', time.ctime())
if __name__ == "__main__":
main()
-threading的使用
-直接利用threading.Thread生成Thread实例
1.t = threading.Thread(target=xxx, args=(xxx,))
2.t.start();启动多线程
3.t.join():等待多线程执行完成
4.案例04
'''
利用time函数,生成两个函数
利用多线程调用
计算总的运行时间
练习带参数的多线程启动方法
'''
import time
import threading
def loop1(in1):
#ctime得到当前时间
print('Start loop 1 at:', time.ctime())
#把参数打印出来
print("我是参数", in1)
#睡眠多长时间,单位是秒
time.sleep(4)
print('End loop 1 at:', time.ctime())
def loop2(in1, in2):
#ctime得到当前时间
print('Start loop 2 at:', time.ctime())
#把参数打印出来
print("我是参数", in1, "和参数", in2)
#睡眠多长时间,单位是秒
time.sleep(2)
print('End loop 2 at:', time.ctime())
def main():
print("Starting at:", time.ctime())
#生成threading.Thread实例
t1 = threading.Thread(target=loop1, args=("刘亦菲",))
t1.start()
t2 = threading.Thread(target=loop2, args=("刘亦菲2", "刘亦菲3"))
t2.start()
print('All done at:', time.ctime())
if __name__ == "__main__":
main()
-05.案例05:加入join后比较跟案例04的结果的异同
'''
利用time函数,生成两个函数
利用多线程调用
计算总的运行时间
练习带参数的多线程启动方法
'''
import time
import threading
def loop1(in1):
#ctime得到当前时间
print('Start loop 1 at:', time.ctime())
#把参数打印出来
print("我是参数", in1)
#睡眠多长时间,单位是秒
time.sleep(4)
print('End loop 1 at:', time.ctime())
def loop2(in1, in2):
#ctime得到当前时间
print('Start loop 2 at:', time.ctime())
#把参数打印出来
print("我是参数", in1, "和参数", in2)
#睡眠多长时间,单位是秒
time.sleep(2)
print('End loop 2 at:', time.ctime())
def main():
print("Starting at:", time.ctime())
#生成threading.Thread实例
t1 = threading.Thread(target=loop1, args=("刘亦菲",))
t1.start()
t2 = threading.Thread(target=loop2, args=("刘亦菲2", "刘亦菲3"))
t2.start()
t1.join()
t2.join()
print('All done at:', time.ctime())
if __name__ == "__main__":
main()
-守护线程-daemon
-如果在程序中将子线程设置成守护线程,则子线程会在主线程结束的时候自动退出
-一般认为,守护线程不重要或者不允许离开主线程独立运行
-守护线程案例能否有效果跟环境相关
-案例06非守护线程
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")
-案例07守护线程
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.setDaemon(True)
#t1.setDaemon = True
t1.start()
time.sleep(1)
print("Main thread end")
-线程的常用属性
-threading.currentThread:返回当前线程变量
-threading.enumerate:返回一个包含正则运行的线程list,正在运行的线程指的是线程启动后、结束前,不包括启动前和终止后的线程
-threading.activeCount:返回正在运行的线程数量,效果跟len(threading.enumerate())相同
-thr.setName:给线程设置名字
-thr.getName:得到线程的名字
-案例08:
import time
import threading
def loop1():
#ctime得到当前的时间
print("Start loop 1 at:", time.ctime())
#睡眠多长时间,单位是秒
time.sleep(4)
print("End loop 1 at:", time.ctime())
def loop2():
#ctime得到当前的时间
print("Start loop 2 at:", time.ctime())
#睡眠多长时间,单位是秒
time.sleep(2)
print("End loop 2 at:", time.ctime())
def loop3():
#ctime得到当前的时间
print("Start loop 3 at:", time.ctime())
#睡眠多长时间,单位是秒
time.sleep(5)
print("End loop 3 at:", time.ctime())
def main():
print("Starting at:", time.ctime())
#生成threading.Tread实例
t1 = threading.Thread(target=loop1, args=())
#setName是给每一个子线程设置一个名字
t1.setName("THR_1")
t1.start()
t2 = threading.Thread(target=loop2, args=())
#setName是给每一个子线程设置一个名字
t2.setName("THR_2")
t2.start()
t3 = threading.Thread(target=loop3, args=())
#setName是给每一个子线程设置一个名字
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()
-直接继承自threading.Thread
-直接继承Thread
-重写run函数
-类实例可以直接运行
-案例09
#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!!!")
-案例10:工业风案例
import threading
from time import sleep,ctime
loop = [4,2]
class ThreadFunc:
def __init__(self, name):
self.name = name
def loop(self, nloop, nsec):
'''
:param nloop:loop函数名称
:param nsec:系统休眠时间
:return:
'''
print("Start loop", nloop, "at", ctime())
sleep(nsec)
print("Done loop", nloop, "at", ctime())
def main():
print("Start at:", 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=("LOOP2", 2))
#常见错误写法
# t1 = threading.Thread(target=ThreadFunc('loop').loop(100,4))
# t2 = threading.Thread(target=ThreadFunc('loop').loop(100,2))
t1.start()
t2.start()
t1.join()
t2.join()
print("All done at:", ctime())
if __name__ == "__main__":
main()
-共享变量
-共享变量:当多个线程同时访问一个变量的时候,回产生共享变量的问题
-案例11
import threading
sum = 0
loopSum = 1000000
def myAdd():
global sum, loopSum
for i in range(1, loopSum):
sum += 1
def myMinu():
global sum, loopSum
for i in range(1, loopSum):
sum -= 1
if __name__ == "__main__":
#myAdd()
#print(sum)
#myAdd()
#print(myMinu)
print("Starting....{0}".format(sum))
#开始多线程的实例,看执行结果是否一样
t1 = threading.Thread(target=myAdd, args=())
t2 = threading.Thread(target=myMinu, args=())
t1.start()
t2.start()
t1.join()
t2.join()
print("Done.....{0}".format(sum))
-解决变量:锁,信号灯
-锁(Lock):
-是一个标志,表示一个线程在占用一些资源
-使用方法:
-上锁
-使用共享资源,放心使用
-取消锁,释放锁
-案例12:
import threading
sum = 0
loopSum = 1000000
lock = threading.Lock()
def myAdd():
global sum, loopSum
for i in range(1, loopSum):
#上锁,申请锁
lock.acquire()
sum += 1
#释放锁
lock.release()
def myMinu():
global sum, loopSum
for i in range(1, loopSum):
lock.acquire()
sum -= 1
lock.release()
if __name__ == "__main__":
print("Starting.....{0}".format(sum))
#开始多线程的实例,看执行结果是否一样
t1 = threading.Thread(target=myAdd, args=())
t2 = threading.Thread(target=myMinu, args=())
t1.start()
t2.start()
t1.join()
t2.join()
print("Done......{0}".format(sum))
-锁谁:哪个资源需要多个线程共享,锁哪个
-理解锁:锁其实不是锁住谁,而是一个令牌
-线程安全问题:
-如果一个资源/变量,它对于多线程来讲,不用加锁也不会引起任何问题,则称为线程安全
-线程不安全变量类型:list,set,dict
-线程安全变量的类型:queue(队列)
-生产者消费者问题
-一个模型,可以用来搭建消息队列。
-queue是一个用来存放变量的数据结构,特点是先进先出,内部元素排队,可以理解成一个特殊的list
-案例13
import threading
import 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 = 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()
-死锁问题,案例14
import threading
import time
lock_1 = threading.Lock()
lock_2 = threading.Lock()
def func_1():
print("func_1 starting.......")
lock_1.acquire()
print("func_1申请了 lock_1....")
time.sleep(2)
print("func_1等待了lock_2........")
lock_2.acquire()
print("func_1申请了lock_2.....")
lock_2.release()
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("func_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("主程序结束......")
-锁的等待时间问题
-案例15
import threading
import 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("func_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注定没有申请到func_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("func_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("主程序结束......")
-semaphore
-允许一个资源最多由几个多线程同时使用
-案例16
import threading
import 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
-案例17
-Timer是利用多线程,在指定时间后启动一个功能
import threading
import time
def func():
print("I am running........")
time.sleep(4)
print("I am done.......")
if __name__ == "__main__":
t = threading.Timer(6, func)
t.start()
i = 0
while True:
print("{0}**************".format(i))
time.sleep(3)
i += 1
-可重入锁
-一个锁,可以被一个线程多次申请
-主要解决递归调用的时候,需要申请锁的情况
-案例18
import threading
import time
class MyThread(threading.Thread):
def run(self):
global num
time.sleep(1)
if mutex.acquire(1):
num = num+1
msg = self.name + 'set num to '+str(num)
print(msg)
mutex.acquire()
mutex.release()
mutex.release()
num = 0
mutex = threading.RLock()
def testTh():
for i in range(5):
t = MyThread()
t.start()
if __name__ == "__main__":
testTh()
# 线程替代方案
- subprocess
-完全跳过线程,使用进程
-是派生进程的主要替代方案
-Python2.4后引入
- multiprocessiong
-使用threading接口派生,使用子进程
-允许为多核或者多cpu派生进程,接口跟threading非常相似
-Python2.6
- concurrent.futures
-新的异步执行模块
-任务级别的操作
-Python个3.2后引入
# 多进程
- 进程间通讯(InterprocessCommunication,IPC)
-进程之间无任何共享状态
-进程的创建
-直接生成Process实例对象,案例19
import multiprocessing
from time import sleep
from time import ctime
def clock(interval):
while True:
print("The time is {}".format(ctime()))
sleep(interval)
if __name__ == "__main__":
p = multiprocessing.Process(target=clock, args=(5,))
p.start()
while True:
print('sleeping.......')
sleep(1)
- 派生子类, 案例20
import multiprocessing
from time import sleep, ctime
class ClockProcess(multiprocessing.Process):
'''
两个函数比较重要
1.init 构造函数
2.run
'''
def __init__(self, interval):
super().__init__()
self.interval = interval
def run(self):
while True:
print("The time is {}".format(ctime()))
sleep(self.interval)
if __name__ == "__main__":
p = ClockProcess(3)
p.start()
while True:
print('sleeping......')
sleep(1)
- 在os中查看pid,ppid以及它们的关系
- 案例21
from multiprocessing import Process
import os
def info(title):
print(title)
print('moudle name:', __name__)
#得到父进程的id
print('parent process:', os.getppid())
#得到本身进程的id
print('process id:', os.getpid())
def f(name):
info('function f')
print('hello', name)
if __name__ == '__main__':
info('main line')
p = Process(target=f, args=('bob',))
p.start()
p.join()
- 生成者消费者模型
- JoinableQueue
-案例22
import multiprocessing
from time import ctime
def consumer(input_q):
print("Into consumer:", ctime())
while True:
# 处理项
item = input_q.get()
print("pull", item, "out of q")#此处替换为有用的工作
input_q.task_done()#发出信号通知任务完成
print("Out of consumer:", ctime())# 此句未执行,因为q.join()收集到四个task_done()信号后,主进程启动,未等到print此句完成
def producer(sequence, output_q):
print("Into procuder:", ctime())
for item in sequence:
output_q.put(item)
print("put", item, "into q")
print("Out of procuder:", ctime())
# 建立进程
if __name__ == "__main__":
q = multiprocessing.JoinableQueue()
# 运行消费者模型
cons_p = multiprocessing.Process(target=consumer, args=(q,))
cons_p.daemon = True
cons_p.start()
# 生成多个项,sequence代表要发送给消费者的项序列
#在实践中,这可能是生成器的输出或者通过一些其他方式生成出来
sequence = [1,2,3,4]
producer(sequence, q)
#等待所有项被处理
q.join()
- 队列中哨兵的使用,案例23
import multiprocessing
from time import ctime
#设置哨兵问题
def consumer(input_q):
print("Into consumer:", ctime())
while True:
item = input_q.get()
if item is None:
break
print("pull", item, "out of q")
print("Out of consumer:", ctime()) ##此句执行完成,再转入主进程
def producer(sequence, output_q):
print("Into procuder:", ctime())
for item in sequence:
output_q.put(item)
print("put", item, "into q")
print("Out of procuder:", ctime())
if __name__ == "__main__":
q = multiprocessing.Queue()
cons_p = multiprocessing.Process(target=consumer, args=(q,))
cons_p.start()
sequence = [1,2,3,4]
producer(sequence, q)
q.put(None)
cons_p.join()
- 哨兵的改进,案例24
import multiprocessing
from time import ctime
#设置哨兵问题
def consumer(input_q):
print("Into consumer:", ctime())
while True:
item = input_q.get()
if item is None:
break
print("pull", item, "out of q")
print("Out of consumer:", ctime()) ##此句执行完成,再转入主进程
def producer(sequence, output_q):
print("Into procuder:", ctime())
for item in sequence:
output_q.put(item)
print("put", item, "into q")
print("Out of procuder:", ctime())
if __name__ == "__main__":
q = multiprocessing.Queue()
cons_p1 = multiprocessing.Process(target=consumer, args=(q,))
cons_p1.start()
cons_p2 = multiprocessing.Process(target=consumer, args=(q,))
cons_p2.start()
sequence = [1,2,3,4]
producer(sequence, q)
q.put(None)
q.put(None) ##多个客户,增加多个None
cons_p1.join()
cons_p2.join()
-https://www.cnblogs.com/jokerbj/p/7460260.html
-http://www.dabeaz.com/python/UnderstandingGIL.pdf
# 多线程 vs 多进程
-程序:一堆代码以文本形式存入一个文档
-进程:程序运行的一个状态
-包含地址空间、内存、数据栈等
-每个进程有自己完全独立的运行环境,多进程共享数据是一个问题
-线程:
-一个进程就是独立运行片段,一个进程可以有多个线程
-轻量化的进程
-一个进程的多个线程间共享数据和上下文运行环境
-共享互斥问题
-全局解释器锁(GIL)
-Python代码的执行是由Python虚拟机进行控制
-在主循环中只能有一个控制线程在执行
-Python包
-thread包:有问题,不好用,python3改成了_thread
-threading:通行的包
-案例01:顺序执行,耗时比较长
'''
利用time函数,生成两个函数
顺序调用
计算总的运行时间
'''
import time
def loop1():
#ctime得到当前时间
print('Start loop 1 at :', time.ctime())
#睡眠多长时间,单位是秒
time.sleep(4)
print('End loop 1 at :', time.ctime())
def loop2():
#ctime得到当前时间
print('Start loop 2 at:', time.ctime())
#睡眠多长时间,单位是秒
time.sleep(2)
print('End loop 2 at:', time.ctime())
def main():
print("Starting at:", time.ctime())
loop1()
loop2()
print('All done at:', time.ctime())
if __name__ == "__main__":
main()
-案例02:案例01的另外一个不被推荐的改变(调用_thread包)
改用多线程,缩短总时间,使用_thread
'''
利用time函数,生成两个函数
顺序调用
计算总的运行时间
'''
import time
import _thread as thread
def loop1():
#ctime得到当前时间
print('Start loop 1 at :', time.ctime())
#睡眠多长时间,单位是秒
time.sleep(4)
print('End loop 1 at :', time.ctime())
def loop2():
#ctime得到当前时间
print('Start loop 2 at:', time.ctime())
#睡眠多长时间,单位是秒
time.sleep(2)
print('End loop 2 at:', time.ctime())
def main():
print("Starting at:", time.ctime())
#启动多线程的意思是用多线程去执行某个函数
#启动多线程函数为start_new_thead
#参数两个,一个是需要运行的函数名,第二是函数的参数作为元组使用,为空则使用空元祖
#注意:如果函数只有一个参数,那么后面需要一个逗号
thread.start_new_thread(loop1, ())
thread.start_new_thread(loop2, ())
print('All done at:', time.ctime())
if __name__ == "__main__":
main()
-案例03:多线程,传参数
'''
利用time函数,生成两个函数
利用多线程调用
计算总的运行时间
练习带参数的多线程启动方法
'''
import time
import _thread as thread
def loop1(in1):
#ctime得到当前时间
print('Start loop 1 at:', time.ctime())
#把参数打印出来
print("我是参数", in1)
#睡眠多长时间,单位是秒
time.sleep(4)
print('End loop 1 at:', time.ctime())
def loop2(in1, in2):
#ctime得到当前时间
print('Start loop 2 at:', time.ctime())
#把参数打印出来
print("我是参数", in1, "和参数", in2)
#睡眠多长时间,单位是秒
time.sleep(2)
print('End loop 2 at:', time.ctime())
def main():
print("Starting at:", time.ctime())
#启动多线程的意思是用多线程去执行某个函数
#启动多线程函数为start_new_thead
#参数两个,一个是需要运行的函数名,第二是函数的参数作为元组使用,为空则使用空元祖
#注意:如果函数只有一个参数,那么后面需要一个逗号
thread.start_new_thread(loop1, ("刘亦菲1",))
thread.start_new_thread(loop2, ("刘亦菲2","刘亦菲3"))
print('All done at:', time.ctime())
if __name__ == "__main__":
main()
-threading的使用
-直接利用threading.Thread生成Thread实例
1.t = threading.Thread(target=xxx, args=(xxx,))
2.t.start();启动多线程
3.t.join():等待多线程执行完成
4.案例04
'''
利用time函数,生成两个函数
利用多线程调用
计算总的运行时间
练习带参数的多线程启动方法
'''
import time
import threading
def loop1(in1):
#ctime得到当前时间
print('Start loop 1 at:', time.ctime())
#把参数打印出来
print("我是参数", in1)
#睡眠多长时间,单位是秒
time.sleep(4)
print('End loop 1 at:', time.ctime())
def loop2(in1, in2):
#ctime得到当前时间
print('Start loop 2 at:', time.ctime())
#把参数打印出来
print("我是参数", in1, "和参数", in2)
#睡眠多长时间,单位是秒
time.sleep(2)
print('End loop 2 at:', time.ctime())
def main():
print("Starting at:", time.ctime())
#生成threading.Thread实例
t1 = threading.Thread(target=loop1, args=("刘亦菲",))
t1.start()
t2 = threading.Thread(target=loop2, args=("刘亦菲2", "刘亦菲3"))
t2.start()
print('All done at:', time.ctime())
if __name__ == "__main__":
main()
-05.案例05:加入join后比较跟案例04的结果的异同
'''
利用time函数,生成两个函数
利用多线程调用
计算总的运行时间
练习带参数的多线程启动方法
'''
import time
import threading
def loop1(in1):
#ctime得到当前时间
print('Start loop 1 at:', time.ctime())
#把参数打印出来
print("我是参数", in1)
#睡眠多长时间,单位是秒
time.sleep(4)
print('End loop 1 at:', time.ctime())
def loop2(in1, in2):
#ctime得到当前时间
print('Start loop 2 at:', time.ctime())
#把参数打印出来
print("我是参数", in1, "和参数", in2)
#睡眠多长时间,单位是秒
time.sleep(2)
print('End loop 2 at:', time.ctime())
def main():
print("Starting at:", time.ctime())
#生成threading.Thread实例
t1 = threading.Thread(target=loop1, args=("刘亦菲",))
t1.start()
t2 = threading.Thread(target=loop2, args=("刘亦菲2", "刘亦菲3"))
t2.start()
t1.join()
t2.join()
print('All done at:', time.ctime())
if __name__ == "__main__":
main()
-守护线程-daemon
-如果在程序中将子线程设置成守护线程,则子线程会在主线程结束的时候自动退出
-一般认为,守护线程不重要或者不允许离开主线程独立运行
-守护线程案例能否有效果跟环境相关
-案例06非守护线程
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")
-案例07守护线程
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.setDaemon(True)
#t1.setDaemon = True
t1.start()
time.sleep(1)
print("Main thread end")
-线程的常用属性
-threading.currentThread:返回当前线程变量
-threading.enumerate:返回一个包含正则运行的线程list,正在运行的线程指的是线程启动后、结束前,不包括启动前和终止后的线程
-threading.activeCount:返回正在运行的线程数量,效果跟len(threading.enumerate())相同
-thr.setName:给线程设置名字
-thr.getName:得到线程的名字
-案例08:
import time
import threading
def loop1():
#ctime得到当前的时间
print("Start loop 1 at:", time.ctime())
#睡眠多长时间,单位是秒
time.sleep(4)
print("End loop 1 at:", time.ctime())
def loop2():
#ctime得到当前的时间
print("Start loop 2 at:", time.ctime())
#睡眠多长时间,单位是秒
time.sleep(2)
print("End loop 2 at:", time.ctime())
def loop3():
#ctime得到当前的时间
print("Start loop 3 at:", time.ctime())
#睡眠多长时间,单位是秒
time.sleep(5)
print("End loop 3 at:", time.ctime())
def main():
print("Starting at:", time.ctime())
#生成threading.Tread实例
t1 = threading.Thread(target=loop1, args=())
#setName是给每一个子线程设置一个名字
t1.setName("THR_1")
t1.start()
t2 = threading.Thread(target=loop2, args=())
#setName是给每一个子线程设置一个名字
t2.setName("THR_2")
t2.start()
t3 = threading.Thread(target=loop3, args=())
#setName是给每一个子线程设置一个名字
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()
-直接继承自threading.Thread
-直接继承Thread
-重写run函数
-类实例可以直接运行
-案例09
#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!!!")
-案例10:工业风案例
import threading
from time import sleep,ctime
loop = [4,2]
class ThreadFunc:
def __init__(self, name):
self.name = name
def loop(self, nloop, nsec):
'''
:param nloop:loop函数名称
:param nsec:系统休眠时间
:return:
'''
print("Start loop", nloop, "at", ctime())
sleep(nsec)
print("Done loop", nloop, "at", ctime())
def main():
print("Start at:", 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=("LOOP2", 2))
#常见错误写法
# t1 = threading.Thread(target=ThreadFunc('loop').loop(100,4))
# t2 = threading.Thread(target=ThreadFunc('loop').loop(100,2))
t1.start()
t2.start()
t1.join()
t2.join()
print("All done at:", ctime())
if __name__ == "__main__":
main()
-共享变量
-共享变量:当多个线程同时访问一个变量的时候,回产生共享变量的问题
-案例11
import threading
sum = 0
loopSum = 1000000
def myAdd():
global sum, loopSum
for i in range(1, loopSum):
sum += 1
def myMinu():
global sum, loopSum
for i in range(1, loopSum):
sum -= 1
if __name__ == "__main__":
#myAdd()
#print(sum)
#myAdd()
#print(myMinu)
print("Starting....{0}".format(sum))
#开始多线程的实例,看执行结果是否一样
t1 = threading.Thread(target=myAdd, args=())
t2 = threading.Thread(target=myMinu, args=())
t1.start()
t2.start()
t1.join()
t2.join()
print("Done.....{0}".format(sum))
-解决变量:锁,信号灯
-锁(Lock):
-是一个标志,表示一个线程在占用一些资源
-使用方法:
-上锁
-使用共享资源,放心使用
-取消锁,释放锁
-案例12:
import threading
sum = 0
loopSum = 1000000
lock = threading.Lock()
def myAdd():
global sum, loopSum
for i in range(1, loopSum):
#上锁,申请锁
lock.acquire()
sum += 1
#释放锁
lock.release()
def myMinu():
global sum, loopSum
for i in range(1, loopSum):
lock.acquire()
sum -= 1
lock.release()
if __name__ == "__main__":
print("Starting.....{0}".format(sum))
#开始多线程的实例,看执行结果是否一样
t1 = threading.Thread(target=myAdd, args=())
t2 = threading.Thread(target=myMinu, args=())
t1.start()
t2.start()
t1.join()
t2.join()
print("Done......{0}".format(sum))
-锁谁:哪个资源需要多个线程共享,锁哪个
-理解锁:锁其实不是锁住谁,而是一个令牌
-线程安全问题:
-如果一个资源/变量,它对于多线程来讲,不用加锁也不会引起任何问题,则称为线程安全
-线程不安全变量类型:list,set,dict
-线程安全变量的类型:queue(队列)
-生产者消费者问题
-一个模型,可以用来搭建消息队列。
-queue是一个用来存放变量的数据结构,特点是先进先出,内部元素排队,可以理解成一个特殊的list
-案例13
import threading
import 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 = 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()
-死锁问题,案例14
import threading
import time
lock_1 = threading.Lock()
lock_2 = threading.Lock()
def func_1():
print("func_1 starting.......")
lock_1.acquire()
print("func_1申请了 lock_1....")
time.sleep(2)
print("func_1等待了lock_2........")
lock_2.acquire()
print("func_1申请了lock_2.....")
lock_2.release()
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("func_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("主程序结束......")
-锁的等待时间问题
-案例15
import threading
import 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("func_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注定没有申请到func_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("func_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("主程序结束......")
-semaphore
-允许一个资源最多由几个多线程同时使用
-案例16
import threading
import 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
-案例17
-Timer是利用多线程,在指定时间后启动一个功能
import threading
import time
def func():
print("I am running........")
time.sleep(4)
print("I am done.......")
if __name__ == "__main__":
t = threading.Timer(6, func)
t.start()
i = 0
while True:
print("{0}**************".format(i))
time.sleep(3)
i += 1
-可重入锁
-一个锁,可以被一个线程多次申请
-主要解决递归调用的时候,需要申请锁的情况
-案例18
import threading
import time
class MyThread(threading.Thread):
def run(self):
global num
time.sleep(1)
if mutex.acquire(1):
num = num+1
msg = self.name + 'set num to '+str(num)
print(msg)
mutex.acquire()
mutex.release()
mutex.release()
num = 0
mutex = threading.RLock()
def testTh():
for i in range(5):
t = MyThread()
t.start()
if __name__ == "__main__":
testTh()
# 线程替代方案
- subprocess
-完全跳过线程,使用进程
-是派生进程的主要替代方案
-Python2.4后引入
- multiprocessiong
-使用threading接口派生,使用子进程
-允许为多核或者多cpu派生进程,接口跟threading非常相似
-Python2.6
- concurrent.futures
-新的异步执行模块
-任务级别的操作
-Python个3.2后引入
# 多进程
- 进程间通讯(InterprocessCommunication,IPC)
-进程之间无任何共享状态
-进程的创建
-直接生成Process实例对象,案例19
import multiprocessing
from time import sleep
from time import ctime
def clock(interval):
while True:
print("The time is {}".format(ctime()))
sleep(interval)
if __name__ == "__main__":
p = multiprocessing.Process(target=clock, args=(5,))
p.start()
while True:
print('sleeping.......')
sleep(1)
- 派生子类, 案例20
import multiprocessing
from time import sleep, ctime
class ClockProcess(multiprocessing.Process):
'''
两个函数比较重要
1.init 构造函数
2.run
'''
def __init__(self, interval):
super().__init__()
self.interval = interval
def run(self):
while True:
print("The time is {}".format(ctime()))
sleep(self.interval)
if __name__ == "__main__":
p = ClockProcess(3)
p.start()
while True:
print('sleeping......')
sleep(1)
- 在os中查看pid,ppid以及它们的关系
- 案例21
from multiprocessing import Process
import os
def info(title):
print(title)
print('moudle name:', __name__)
#得到父进程的id
print('parent process:', os.getppid())
#得到本身进程的id
print('process id:', os.getpid())
def f(name):
info('function f')
print('hello', name)
if __name__ == '__main__':
info('main line')
p = Process(target=f, args=('bob',))
p.start()
p.join()
- 生成者消费者模型
- JoinableQueue
-案例22
import multiprocessing
from time import ctime
def consumer(input_q):
print("Into consumer:", ctime())
while True:
# 处理项
item = input_q.get()
print("pull", item, "out of q")#此处替换为有用的工作
input_q.task_done()#发出信号通知任务完成
print("Out of consumer:", ctime())# 此句未执行,因为q.join()收集到四个task_done()信号后,主进程启动,未等到print此句完成
def producer(sequence, output_q):
print("Into procuder:", ctime())
for item in sequence:
output_q.put(item)
print("put", item, "into q")
print("Out of procuder:", ctime())
# 建立进程
if __name__ == "__main__":
q = multiprocessing.JoinableQueue()
# 运行消费者模型
cons_p = multiprocessing.Process(target=consumer, args=(q,))
cons_p.daemon = True
cons_p.start()
# 生成多个项,sequence代表要发送给消费者的项序列
#在实践中,这可能是生成器的输出或者通过一些其他方式生成出来
sequence = [1,2,3,4]
producer(sequence, q)
#等待所有项被处理
q.join()
- 队列中哨兵的使用,案例23
import multiprocessing
from time import ctime
#设置哨兵问题
def consumer(input_q):
print("Into consumer:", ctime())
while True:
item = input_q.get()
if item is None:
break
print("pull", item, "out of q")
print("Out of consumer:", ctime()) ##此句执行完成,再转入主进程
def producer(sequence, output_q):
print("Into procuder:", ctime())
for item in sequence:
output_q.put(item)
print("put", item, "into q")
print("Out of procuder:", ctime())
if __name__ == "__main__":
q = multiprocessing.Queue()
cons_p = multiprocessing.Process(target=consumer, args=(q,))
cons_p.start()
sequence = [1,2,3,4]
producer(sequence, q)
q.put(None)
cons_p.join()
- 哨兵的改进,案例24
import multiprocessing
from time import ctime
#设置哨兵问题
def consumer(input_q):
print("Into consumer:", ctime())
while True:
item = input_q.get()
if item is None:
break
print("pull", item, "out of q")
print("Out of consumer:", ctime()) ##此句执行完成,再转入主进程
def producer(sequence, output_q):
print("Into procuder:", ctime())
for item in sequence:
output_q.put(item)
print("put", item, "into q")
print("Out of procuder:", ctime())
if __name__ == "__main__":
q = multiprocessing.Queue()
cons_p1 = multiprocessing.Process(target=consumer, args=(q,))
cons_p1.start()
cons_p2 = multiprocessing.Process(target=consumer, args=(q,))
cons_p2.start()
sequence = [1,2,3,4]
producer(sequence, q)
q.put(None)
q.put(None) ##多个客户,增加多个None
cons_p1.join()
cons_p2.join()