python 线程进程
一 线程的2种调用方式
直接调用
实例1:
import threading
import time def sayhi(num): #定义每个线程要运行的函数 print("running on number:%s" %num) time.sleep(3) if __name__ == '__main__': t1 = threading.Thread(target=sayhi,args=(1,)) #生成一个线程实例
t2 = threading.Thread(target=sayhi,args=(2,)) #生成另一个线程实例 t1.start() #启动线程
t2.start() #启动另一个线程 print(t1.getName()) #获取线程名
print(t2.getName())
继承式调用:
import threading
import time class MyThread(threading.Thread):
def __init__(self,num):
threading.Thread.__init__(self)
self.num = num def run(self):#定义每个线程要运行的函数 print("running on number:%s" %self.num) time.sleep(3) if __name__ == '__main__': t1 = MyThread(1)
t2 = MyThread(2)
t1.start()
t2.start()
join():
在子线程完成运行之前,这个子线程的父线程将一直被阻塞。
import threading
import time def music():
print("begin to listin ---%s"%time.ctime())
time.sleep(3)
print("stop to listin ---%s" % time.ctime()) def game():
print("begin to play game ---%s"%time.ctime())
time.sleep(5)
print("stop to play game ---%s" % time.ctime()) if __name__ == '__main__': t1 = threading.Thread(target=music) t2 = threading.Thread(target=game) t1.start() #创了一个线程对象t1
t1.join() # t1.join就是要等t1执行完了,才会往下执行 (阻塞) t2.start() #创了一个线程对象t2 print("ending......") #主线程
setDaemon(True):
将线程声明为守护线程,必须在start() 方法调用之前设置, 如果不设置为守护线程程序会被无限挂起。这个方法基本和join是相反的。当我们 在程序运行中,执行一个主线程,如果主线程又创建一个子线程,主线程和子线程 就分兵两路,分别运行,那么当主线程完成想退出时,会检验子线程是否完成。如 果子线程未完成,则主线程会等待子线程完成后再退出。但是有时候我们需要的是 只要主线程完成了,不管子线程是否完成,都要和主线程一起退出,这时就可以 用setDaemon方法啦
import threading
import time def music():
print("begin to listin ---%s"%time.ctime())
time.sleep(3)
print("stop to listin ---%s" % time.ctime()) def game():
print("begin to play game ---%s"%time.ctime())
time.sleep(5)
print("stop to play game ---%s" % time.ctime()) if __name__ == '__main__': t1 = threading.Thread(target=music) t2 = threading.Thread(target=game) t2.setDaemon(True) #线程保护, t2会跟随主线程一起结束 一定要写在 start() 方法前 (守护线程)
t1.start() #创了一个线程对象t1
t2.start() #创了一个线程对象t2 print("ending......") #主线程
三 同步锁(Lock)
import time
import threading def addNum():
global num #在每个线程中都获取这个全局变量
# num-=1
lock.acquire()
temp=num
print('--get num:',num )
#time.sleep(0.1)
num =temp-1 #对此公共变量进行-1操作
lock.release() num = 100 #设定一个共享变量
thread_list = []
lock=threading.Lock() for i in range(100):
t = threading.Thread(target=addNum)
t.start()
thread_list.append(t) for t in thread_list: #等待所有线程执行完毕
t.join() print('final num:', num )
请问:同步锁与GIL的关系?
Python的线程在GIL的控制之下,线程之间,对整个python解释器,对python提供的C API的访问都是互斥的,这可以看作是Python内核级的互斥机制。但是这种互斥是我们不能控制的,我们还需要另外一种可控的互斥机制———用户级互斥。内核级通过互斥保护了内核的共享资源,同样,用户级互斥保护了用户程序中的共享资源。
但是如果你有个操作比如 x += 1,这个操作需要多个bytecodes操作,在执行这个操作的多条bytecodes期间的时候可能中途就换thread了,这样就出现了data races的情况了。
四 线程死锁和递归锁
在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁,因为系统判断这部分资源都正在使用,所有这两个线程在无外力作用下将一直等待下去。下面是一个死锁的例子:
import threading,time class myThread(threading.Thread):
def doA(self):
lockA.acquire()
print(self.name,"gotlockA",time.ctime())
time.sleep(3)
lockB.acquire()
print(self.name,"gotlockB",time.ctime())
lockB.release()
lockA.release() def doB(self):
lockB.acquire()
print(self.name,"gotlockB",time.ctime())
time.sleep(2)
lockA.acquire()
print(self.name,"gotlockA",time.ctime())
lockA.release()
lockB.release()
def run(self):
self.doA()
self.doB()
if __name__=="__main__": lockA=threading.Lock()
lockB=threading.Lock()
threads=[]
for i in range(5):
threads.append(myThread())
for t in threads:
t.start()
for t in threads:
t.join()#等待线程结束,后面再讲。
解决办法:使用递归锁
为了支持在同一线程中多次请求同一资源,python提供了“可重入锁”:threading.RLock。RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次acquire。直到一个线程所有的acquire都被release,其他的线程才能获得资源。
递归锁
import threading,time class MyThread(threading.Thread): def actionA(self):
r_lock.acquire()
print("gotA",self.name,time.ctime())
time.sleep(2) r_lock.acquire()
print("gotB",self.name,time.ctime())
time.sleep(1) r_lock.release()
r_lock.release() def actionB(self):
r_lock.acquire()
print("gotC", self.name, time.ctime())
time.sleep(2) r_lock.acquire()
print("gotD", self.name, time.ctime())
time.sleep(1) r_lock.release()
r_lock.release() def run(self):
self.actionA()
self.actionB() if __name__ == '__main__': r_lock = threading.RLock() l = [] for i in range(5):
t = MyThread()
t.start()
l.append(t) for i in l:
i.join() print("ending...")
六 同步条件(Event)
条件同步和条件变量同步差不多意思,只是少了锁功能,因为条件同步设计于不访问共享资源的条件环境。event=threading.Event():条件环境对象,初始值 为False;
event.isSet():返回event的状态值; event.wait():如果 event.isSet()==False将阻塞线程; event.set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度; event.clear():恢复event的状态值为False。
实例1:
import threading,time
class Boss(threading.Thread):
def run(self):
print("BOSS:今晚大家都要加班到22:00。")
event.isSet() or event.set()
time.sleep(5)
print("BOSS:<22:00>可以下班了。")
event.isSet() or event.set()
class Worker(threading.Thread):
def run(self):
event.wait()
print("Worker:哎……命苦啊!")
time.sleep(0.25)
event.clear()
event.wait()
print("Worker:OhYeah!")
if __name__=="__main__":
event=threading.Event()
threads=[]
for i in range(5):
threads.append(Worker())
threads.append(Boss())
for t in threads:
t.start()
for t in threads:
t.join()
实例2:
import threading,time
import random
def light():
if not event.isSet():
event.set() #wait就不阻塞 #绿灯状态
count = 0
while True:
if count < 10:
print('\033[42;1m--green light on---\033[0m')
elif count <13:
print('\033[43;1m--yellow light on---\033[0m')
elif count <20:
if event.isSet():
event.clear()
print('\033[41;1m--red light on---\033[0m')
else:
count = 0
event.set() #打开绿灯
time.sleep(1)
count +=1
def car(n):
while 1:
time.sleep(random.randrange(10))
if event.isSet(): #绿灯
print("car [%s] is running.." % n)
else:
print("car [%s] is waiting for the red light.." %n)
if __name__ == '__main__':
event = threading.Event()
Light = threading.Thread(target=light)
Light.start()
for i in range(3):
t = threading.Thread(target=car,args=(i,))
t.start()
八 多线程利器(queue)
创建一个“队列”对象
import Queue
q = Queue.Queue(maxsize = 10)
Queue.Queue类即是一个队列的同步实现。队列长度可为无限或者有限。可通过Queue的构造函数的可选参数maxsize来设定队列长度。如果maxsize小于1就表示队列长度无限。 将一个值放入队列中
q.put(10)
调用队列对象的put()方法在队尾插入一个项目。put()有两个参数,第一个item为必需的,为插入项目的值;第二个block为可选参数,默认为
1。如果队列当前为空且block为1,put()方法就使调用线程暂停,直到空出一个数据单元。如果block为0,put方法将引发Full异常。 将一个值从队列中取出
q.get()
调用队列对象的get()方法从队头删除并返回一个项目。可选参数为block,默认为True。如果队列为空且block为True,get()就使调用线程暂停,直至有项目可用。如果队列为空且block为False,队列将引发Empty异常。 Python Queue模块有三种队列及构造函数:
1、Python Queue模块的FIFO队列先进先出。 class queue.Queue(maxsize)
2、LIFO类似于堆,即先进后出。 class queue.LifoQueue(maxsize)
3、还有一种是优先级队列级别越低越先出来。 class queue.PriorityQueue(maxsize) 此包中的常用方法(q = Queue.Queue()):
q.qsize() 返回队列的大小
q.empty() 如果队列为空,返回True,反之False
q.full() 如果队列满了,返回True,反之False
q.full 与 maxsize 大小对应
q.get([block[, timeout]]) 获取队列,timeout等待时间
q.get_nowait() 相当q.get(False)
非阻塞 q.put(item) 写入队列,timeout等待时间
q.put_nowait(item) 相当q.put(item, False)
q.task_done() 在完成一项工作之后,q.task_done() 函数向任务已经完成的队列发送一个信号
q.join() 实际上意味着等到队列为空,再执行别的操作
实例:
import time,random
import queue,threading
q = queue.Queue()
def Producer(name):
count = 0
while count <20:
time.sleep(random.randrange(3))
q.put(count)
print('Producer %s has produced %s baozi..' %(name, count))
count +=1
def Consumer(name):
count = 0
while count <20:
time.sleep(random.randrange(4))
if not q.empty():
data = q.get()
print(data)
print('\033[32;1mConsumer %s has eat %s baozi...\033[0m' %(name, data))
else:
print("-----no baozi anymore----")
count +=1
p1 = threading.Thread(target=Producer, args=('A',))
c1 = threading.Thread(target=Consumer, args=('B',))
p1.start()
c1.start()
实例2:
#实现一个线程不断生成一个随机数到一个队列中(考虑使用Queue这个模块)
# 实现一个线程从上面的队列里面不断的取出奇数
# 实现另外一个线程从上面的队列里面不断取出偶数 import random,threading,time
from queue import Queue
#Producer thread
class Producer(threading.Thread):
def __init__(self, t_name, queue):
threading.Thread.__init__(self,name=t_name)
self.data=queue
def run(self):
for i in range(10): #随机产生10个数字 ,可以修改为任意大小
randomnum=random.randint(1,99)
print ("%s: %s is producing %d to the queue!" % (time.ctime(), self.getName(), randomnum))
self.data.put(randomnum) #将数据依次存入队列
time.sleep(1)
print ("%s: %s finished!" %(time.ctime(), self.getName())) #Consumer thread
class Consumer_even(threading.Thread):
def __init__(self,t_name,queue):
threading.Thread.__init__(self,name=t_name)
self.data=queue
def run(self):
while 1:
try:
val_even = self.data.get(1,5) #get(self, block=True, timeout=None) ,1就是阻塞等待,5是超时5秒
if val_even%2==0:
print ("%s: %s is consuming. %d in the queue is consumed!" % (time.ctime(),self.getName(),val_even))
time.sleep(2)
else:
self.data.put(val_even)
time.sleep(2)
except: #等待输入,超过5秒 就报异常
print ("%s: %s finished!" %(time.ctime(),self.getName()))
break
class Consumer_odd(threading.Thread):
def __init__(self,t_name,queue):
threading.Thread.__init__(self, name=t_name)
self.data=queue
def run(self):
while 1:
try:
val_odd = self.data.get(1,5)
if val_odd%2!=0:
print ("%s: %s is consuming. %d in the queue is consumed!" % (time.ctime(), self.getName(), val_odd))
time.sleep(2)
else:
self.data.put(val_odd)
time.sleep(2)
except:
print ("%s: %s finished!" % (time.ctime(), self.getName()))
break
#Main thread
def main():
queue = Queue()
producer = Producer('Pro.', queue)
consumer_even = Consumer_even('Con_even.', queue)
consumer_odd = Consumer_odd('Con_odd.',queue)
producer.start()
consumer_even.start()
consumer_odd.start()
producer.join()
consumer_even.join()
consumer_odd.join()
print ('All threads terminate!') if __name__ == '__main__':
main()
一 进程的调用
调用方式1
from multiprocessing import Process
import time
def f(name):
time.sleep(1)
print('hello', name,time.ctime()) if __name__ == '__main__':
p_list=[]
for i in range(3):
p = Process(target=f, args=('alvin',))
p_list.append(p)
p.start()
for i in p_list:
p.join()
print('end')
调用方式2
from multiprocessing import Process
import time class MyProcess(Process):
def __init__(self):
super(MyProcess, self).__init__()
#self.name = name def run(self):
time.sleep(1)
print ('hello', self.name,time.ctime()) if __name__ == '__main__':
p_list=[]
for i in range(3):
p = MyProcess()
p.start()
p_list.append(p) for p in p_list:
p.join() print('end')
To show the individual process IDs involved, here is an expanded example:
from multiprocessing import Process
import os
import time
def info(title): print("title:",title)
print('parent process:', os.getppid())
print('process id:', os.getpid()) def f(name):
info('function f')
print('hello', name) if __name__ == '__main__':
info('main process line')
time.sleep(1)
print("------------------")
p = Process(target=info, args=('yuan',))
p.start()
p.join()
二 Process类
构造方法:
Process([group [, target [, name [, args [, kwargs]]]]])
group: 线程组,目前还没有实现,库引用中提示必须是None;
target: 要执行的方法;
name: 进程名;
args/kwargs: 要传入方法的参数。
实例方法:
is_alive():返回进程是否在运行。
join([timeout]):阻塞当前上下文环境的进程程,直到调用此方法的进程终止或到达指定的timeout(可选参数)。
start():进程准备就绪,等待CPU调度
run():strat()调用run方法,如果实例进程时未制定传入target,这star执行t默认run()方法。
terminate():不管任务是否完成,立即停止工作进程
属性:
daemon:和线程的setDeamon功能一样
name:进程名字。
pid:进程号。
import time
from multiprocessing import Process def foo(i):
time.sleep(1)
print (p.is_alive(),i,p.pid)
time.sleep(1) if __name__ == '__main__':
p_list=[]
for i in range(10):
p = Process(target=foo, args=(i,))
#p.daemon=True
p_list.append(p) for p in p_list:
p.start()
# for p in p_list:
# p.join() print('main process end')
三 进程间通讯
3.1 进程对列Queue
from multiprocessing import Process, Queue
import queue def f(q,n):
#q.put([123, 456, 'hello'])
q.put(n*n+1)
print("son process",id(q)) if __name__ == '__main__':
q = Queue() #try: q=queue.Queue()
print("main process",id(q)) for i in range(3):
p = Process(target=f, args=(q,i))
p.start() print(q.get())
print(q.get())
print(q.get())
3.2 管道
from multiprocessing import Process,Pipe def foo(conn):
conn.send("ni hao ma")
print(conn.recv())
conn.close() if __name__ == '__main__':
p_conn,c_conn = Pipe() p = Process(target=foo,args=(c_conn,))
p.start() print(p_conn.recv())
p_conn.send("hao ")
p_conn.close()
p.join()
3.3 Managers
from multiprocessing import Process,Manager def foo(d,l,n): d[n] = "1"
d["2"] = 2 l.append(n) if __name__ == '__main__': with Manager() as manager: d = manager.dict() #{} l = manager.list(range(3)) #[0,1,2] p_li = [] for i in range(10):
p = Process(target=foo,args=(d,l,i))
p.start()
p_li.append(p) for t in p_li:
t.join() print(d)
print(l)
四 进程同步
from multiprocessing import Process,Lock def foo(lock,i): lock.acquire()
print("hello %s"%i)
lock.release() if __name__ == '__main__': lock = Lock()
for i in range(10):
Process(target=foo,args=(lock,i)).start()
五 进程池
from multiprocessing import Pool
import time,os def foo(i):
time.sleep(1)
print(i) print("son ",os.getpid()) return "HELLO %s"%i def bar(arg):
print(arg) print("bar ",os.getpid()) if __name__ == '__main__':
pool = Pool() print("main ",os.getpid())
for i in range(100): # 回调函数:就是某个动作或者函数执行成功后再去执行函数
pool.apply_async(func=foo,args=(i,),callback=bar) pool.close()
pool.join() #join 与close调用顺序是固定的 print("end...")
六 协程
Greenlet
from greenlet import greenlet def test1():
print(1)
gr2.switch()
print(4) def test2():
print(2)
gr1.switch()
print(3)
gr1.switch() if __name__ == '__main__':
gr1 = greenlet(test1)
gr2 = greenlet(test2) gr2.switch()
Gevent
import gevent import requests,time start=time.time() def f(url):
print('GET: %s' % url)
resp =requests.get(url)
data = resp.text
print('%d bytes received from %s.' % (len(data), url)) gevent.joinall([ gevent.spawn(f, 'https://www.python.org/'),
gevent.spawn(f, 'https://www.yahoo.com/'),
gevent.spawn(f, 'https://www.baidu.com/'),
gevent.spawn(f, 'https://www.sina.com.cn/'), ]) # f('https://www.python.org/')
#
# f('https://www.yahoo.com/')
#
# f('https://baidu.com/')
#
# f('https://www.sina.com.cn/') print("cost time:",time.time()-start)
python 线程进程的更多相关文章
- python 线程 进程
1.进程与线程优.缺点的比较总言:使用进程和线程的目的,提高执行效率. 进程: 优点:能利用机器的多核性能,同时进行多个操作. 缺点:需要耗费资源,重新开辟内存空间,耗内存. 线程: 优点:共享内存( ...
- python 线程 进程 协程 学习
转载自大神博客:http://www.cnblogs.com/aylin/p/5601969.html 仅供学习使用···· python 线程与进程简介 进程与线程的历史 我们都知道计算机是由硬件和 ...
- python线程进程
多道技术: 多道程序设计技术 所谓多道程序设计技术,就是指允许多个程序同时进入内存并运行.即同时把多个程序放入内存,并允许它们交替在CPU中运行,它们共享系统中的各种硬.软件资源.当一道程序因I/O请 ...
- Python 线程&进程与协程
Python 的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承.Py ...
- python线程,进程,队列和缓存
一.线程 threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. 创建线程的两种方式1.threading.Thread import threading def f1(arg): ...
- python 线程,进程28原则
基于函数实现 from threading import Thread def fun(data, *args, **kwargs): """ :param data: ...
- python 线程/进程模块
线程的基本使用: import threading # ###################### 1.线程的基本使用 def func(arg): print(arg) t = threading ...
- python 线程 进程 标识
s = '%s%s%s%s%s%s%s%s' % ( time.strftime('%Y%m%d %H:%M:%S', time.localtime(time.time())), ' os.getpp ...
- python 线程(一)理论部分
Python线程 进程有很多优点,它提供了多道编程,可以提高计算机CPU的利用率.既然进程这么优秀,为什么还要线程呢?其实,仔细观察就会发现进程还是有很多缺陷的. 主要体现在一下几个方面: 进程只能在 ...
随机推荐
- js最全的十种跨域解决方案
在客户端编程语言中,如javascript和ActionScript,同源策略是一个很重要的安全理念,它在保证数据的安全性方面有着重要的意义.同 源策略规定跨域之间的脚本是隔离的,一个域的脚本不能访问 ...
- Vigenère密码 2012年NOIP全国联赛提高组(字符串模拟)
P1079 Vigenère 密码 题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密 码.Vigenère 密码的加密解密算法简 ...
- python实现汉诺塔程序
# 汉诺塔思想笔记# 认识汉诺塔的目标:把A柱子上的N个盘子移动到C柱子# 递归的思想就是把这个目标分解成三个子目标# 子目标1:将前n-1个盘子从a移动到b上# 子目标2:将最底下的最后一个盘子从a ...
- Web Api之Cors跨域(干货)---大家一定要看清我写的内容哦
Web Api之Cors跨域 要想跨域需要准备一下几步骤 1.创建WebAPI(请按照图片先后顺序来) 2.进入NuGet包管理搜 Microsoft.AspNet.WebApi.Cors 进行下载 ...
- laravel 模型 $table $guarded $hidden
首先以App\User模型为例 1.$table属性 表名,对应数据库中的表名 2.guarded)属性 guarded表示在create()方法中不能被赋值的字段 3.$hidden属性 $hid ...
- [转]C++常用字符串分割方法实例汇总
本文实例汇总了C++常用字符串分割方法,分享给大家供大家参考.具体分析如下: 我们在编程的时候经常会碰到字符串分割的问题,这里总结下,也方便我们以后查询使用. 一.用strtok函数进行字符串分割 原 ...
- GIT学习之路第五天 分支管理
本文参考廖雪峰老师的博客进行总结,完整学习请转廖雪峰博客 5.1创建与合并分支 首先创建dev分支,然后切换dev分支 $git checkout -b dev(包含创建并切换) 等价于<-&g ...
- redis之有序集合类型(Zset)——排行榜的实现
当数据库对排序支持的不是很好,可以利用redis有序集合排序 原文链接:http://blog.csdn.net/loophome/article/details/50373202
- leetcode343 Integer Break
思路: 将n不断拆分3出来直至其小于或等于4. 实现: class Solution { public: int integerBreak(int n) { ] = {, , , }; ) retur ...
- python manage.py syncdb报错:No module named MySQLdb
今天同步数据时出现这个错误: 解决方法: 1.先下载mysql-python 支持1.2.3-2.7版本 MySQL-python 1.2.3 for Windows and Python 2.7, ...