程序:一堆代码以文本形式存入一个文档
进程:程序运行的一个状态
线程
全局解释器锁(GIL)
Python包
# 不使用线程,顺序执行,程序运行时间长
# 利用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()
输出结果为:
Starting at: Tue Nov 27 20:35:53 2018
Start loop 1 at: Tue Nov 27 20:35:53 2018
End loop 1 at: Tue Nov 27 20:35:57 2018
Start loop 2 at: Tue Nov 27 20:35:57 2018
End loop 2 at: Tue Nov 27 20:35:59 2018
All done at: Tue Nov 27 20:35:59 2018
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())
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)
主线程已经结束而子线程仍在继续运行,输出结果为:
Starting at: Tue Nov 27 21:42:32 2018
All done at: Tue Nov 27 21:42:32 2018
Start loop 1 at: Tue Nov 27 21:42:32 2018
Start loop 2 at: Tue Nov 27 21:42:32 2018
End loop 2 at: Tue Nov 27 21:42:34 2018
End loop 1 at: Tue Nov 27 21:42:36 2018
# 使用多线程传递参数
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_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(10)
执行结果如下:
Starting at: Tue Nov 27 21:50:16 2018
All done at: Tue Nov 27 21:50:16 2018
Start loop 1 at: Tue Nov 27 21:50:16 2018
我是参数 往
Start loop 2 at: Tue Nov 27 21:50:16 2018
我是参数 生 和参数 经
End loop 2 at: Tue Nov 27 21:50:18 2018
End loop 1 at: Tue Nov 27 21:50:20 2018
直接使用threading.Thread生成Thread实例
# threading的使用
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())
t1 = threading.Thread(target=loop1,args=("往",))
t1.start()
t2 = threading.Thread(target=loop2,args=("生","经"))
t2.start()
print("All done at:",time.ctime())
if __name__ == "__main__":
main()
while True:
time.sleep(10)
输出结果:
Starting at: Tue Nov 27 21:56:22 2018
Start loop 1 at: Tue Nov 27 21:56:22 2018
我是参数 往
Start loop 2 at: Tue Nov 27 21:56:22 2018
All done at: Tue Nov 27 21:56:22 2018
我是参数 生和参数 经
End loop 2 at: Tue Nov 27 21:56:24 2018
End loop 1 at: Tue Nov 27 21:56:26 2018
守护线程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.setDaemon(True)
t1.start()
time.sleep(1)
print("Main thread end")
输出结果为:
Main thread
Start fun
Main thread end
线程常用属性
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())
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()
time.sleep(3)
for thr in threading.enumerate():
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: Tue Nov 27 22:01:56 2018
Start loop 1 at: Tue Nov 27 22:01:56 2018
Start loop 2 at: Tue Nov 27 22:01:56 2018
Start loop 3 at: Tue Nov 27 22:01:56 2018
End loop 2 at: Tue Nov 27 22:01:58 2018
正在运行的线程的名字是:MainThread
正在运行的线程的名字是:THR_1
正在运行的线程的名字是:THR_3
正在运行的子线程数量为:3
All done at: Tue Nov 27 22:01:59 2018
End loop 1 at: Tue Nov 27 22:02:00 2018
End loop 3 at: Tue Nov 27 22:02:01 2018
直接继承来自threading.Thread
import threading
import time
# 类需要继承threading.Thread
class MyThread(threading.Thread):
def __init__(self,arg):
super(MyThread,self).__init__()
self.arg = arg
# 必须重写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!!!!!!")
结果为:
The args for this class is 0
The args for this class is 1
The args for this class is 2
The args for this class is 3
The args for this class is 4
Main thread is done!!!!!!
共享变量:当多个线程同时访问一个变量的时候,会产生共享变量的问题
解决方法:锁
锁(Lock):
# 此程序使用锁
import threading
# 定义变量
sum = 1
loopSum = 10000
#调用锁
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))
线程安全问题
生产者消费者问题
#encoding = utf-8
import threading
import time
#python 2
#from Queue import Queue
#python3
import queue
class Producter(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 Cousumer(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 = Producter()
p.start()
for i in range(5):
c = Cousumer()
c.start()
死锁问题
Semaphore()
import threading
import time
# 参数定义最多3个线程同时使用线程
semaphore = threading.Semaphore(3)
def func():
if semaphore.acquire():
for i in range(5):
print(threading.current_thread().getName() + ' get semaphore')
time.sleep(15)
semaphore.release()
print(threading.current_thread().getName() + ' release semaphore')
for i in range(8):
t1 = threading.Thread(target=func)
t1.start()
threading.Timer
可重入锁(RLock())
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()
如果此处使用Lock,普通锁,程序无法执行报错,使用RLock,结果如下
Thread-6 set num to 1
Thread-7 set num to 2
Thread-8 set num to 3
Thread-9 set num to 4
Thread-10 set num to 5
进程间通讯(InterprocessCommunication,IPC)
进程之间无任何共享状态
进程的创建
直接实例化
import multiprocessing
from time import sleep,ctime
def clock(interval):
while True:
print("The time is {0}".format(ctime()))
sleep(interval)
if __name__ == "__main__":
p = multiprocessing.Process(target=clock,args=(5,))
p.start()
while True:
print("Sleep...")
sleep(1)
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 {0}".format(ctime()))
sleep(self.interval)
if __name__ == "__main__":
p = ClockProcess(3)
p.start()
while True:
print("Sleep...")
sleep(1)
在os中查看pid、ppid以及关系
from multiprocessing import Process
import os
def info(title):
print(title)
print('module name:',__name__)
#得到父进程的id
print("parent process id:",os.getppid())
#得到自身进程的id
print("process is:",os.getpid())
def f(name):
info("function-1")
print("hello",name)
if __name__ == '__main__':
info('main line')
p = Process(target=f,args=('cher',))
p.start()
程序结果:
main line
module name: __main__
parent process id: 4780
process is: 4776
function-1
module name: __mp_main__
parent process id: 4776
process is: 5772
hello cher
生产消费者模型
JoinableQueue的使用,consumer函数依据队列queue从仓库中取出产品,producer函数生产产品根据队列queue放入仓库。
import multiprocessing
from time import sleep,ctime
def consumer(input_q):
print("Into consumer:{0}".format(ctime()))
while True:
#处理项
item = input_q.get()
print("pull",item,"out of q")
#发出信号通知任务完成
input_q.task_done()
# 此句未被执行,因为q.join()收集到四个task_done()信号后,主进程启动,未等到print此句完
# print("Out of consumer:{0}".format(ctime()))
def producer(sequence,output_q):
print("Into producer:",format(ctime()))
for item in sequence:
output_q.put(item)
print("put",item,"into q")
print("Out of producer:",format(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()
程序运行结果:
Into producer: Wed Nov 28 22:00:41 2018
put 1 into q
put 2 into q
put 3 into q
put 4 into q
Out of producer: Wed Nov 28 22:00:41 2018
Into consumer:Wed Nov 28 22:00:41 2018
pull 1 out of q
pull 2 out of q
pull 3 out of q
pull 4 out of q
队列queue中哨兵的使用,即控制生产消费者关系是否继续维持
import multiprocessing
from time import sleep,ctime
#设置哨兵
def consumer(input_q):
print("Into consumer:{0}".format(ctime()))
while True:
item = input_q.get()
if item is None:
break
print("pull",item,"out of q")
# 此句执行完成,在转入主线程
print("Out of consumer:{0}".format(ctime()))
def producer(sequence,output_q):
print("Into producer:",format(ctime()))
for item in sequence:
output_q.put(item)
print("put",item,"into q")
print("Out of producer:",format(ctime()))
if __name__ == "__main__":
q = multiprocessing.Queue()
#运行消费者进程
cons_p1 = multiprocessing.Process(target=consumer,args=(q,))
cons_p1.start()
sequence = [1,2,3,4]
producer(sequence,q)
#有多少个消费者放置多少个None
q.put(None)
cons_p1.join()
运行结果:
Into producer: Wed Nov 28 22:21:56 2018
put 1 into q
put 2 into q
put 3 into q
put 4 into q
Out of producer: Wed Nov 28 22:21:56 2018
Into consumer:Wed Nov 28 22:21:56 2018
pull 1 out of q
pull 2 out of q
pull 3 out of q
pull 4 out of q
Out of consumer:Wed Nov 28 22:21:56 2018