python 其实是单线程程序,之所以有多线程是因为它是利用上下分时的功能让人感觉看起来是多线程。
python 多线程不适合cpu密集操作性的任务,适合io操作密集的任务。
多并发效果:
import multiprocessing
import time
def f(name):
print('hello', name)
if __name__ == '__main__': #注意这里的name==main,不是name==name
for i in range(10):
p = multiprocessing.Process(target=f, args=(i,)) #定义多进程对象
p.start()
import multiprocessing也可以写成from
multiprocessing
import
Process,但是下面使用的时候,就可以直接使用
Process方法了。
import time,threading
import multiprocessing
def thread_run():
print threading.get_ident() #得到线程号
def run1(name):
time.sleep(1)
print 'hello',name
t=threading.Thread(target=thread_run,) #定义线程对象
t.start()
if __name__ == '__main__':
for i in range(10):
p = multiprocessing.Process(target = run1 ,args=(i,)) #定义进程对象
p.start()
进程间通讯
Queues:这里的Queues跟线程中的queue不是一样的,这里指的是from
multiprocessing
import
Queue进程中的Queue
#coding:utf-8
from multiprocessing import Queue,Process
def run2(qq):
qq.put('123')
if __name__=='__main__':
q=Queue()
p=Process(target=run2,args=(q,))
p.start()
print q.get()
Pipes(管道)
跟socket的send、recv一样可以发送接收信息
from multiprocessing import Process, Pipe
def f(conn):
conn.send([42, None, 'hello from child'])
conn.send([42, None, 'hello from child2'])#双方可以互换的发送和接受信息。
print("from parent:",conn.recv())
conn.close()
if __name__ == '__main__':
parent_conn, child_conn = Pipe()
p = Process(target=f, args=(child_conn,))
p.start()
print(parent_conn.recv()) # prints "[42, None, 'hello']"
print(parent_conn.recv()) # prints "[42, None, 'hello']"
parent_conn.send("小王可好")
p.join() #等待p进程的结束
Managers
Managersk可以实现列表,字典,命名空间,锁,rlock,semaphore,boundedsemaphore,condition,事件队列,势垒,和阵列数据的共享和修改。
#coding:utf-8
from multiprocessing import Process, Manager
import os,time
def f(d, l):
d[1] = '1'
d['2'] = 2
d[0.25] = None
l.append(os.getpid()) #将当期进程id添加到列表中
print(l)
time.sleep(2)
if __name__ == '__main__':
with Manager() as manager:
d = manager.dict() #可在多个进程中共享数据的字典
l = manager.list(range(5)) #可在多个进程中共享5个数据的列表
p_list = []
for i in range(10):
p = Process(target=f, args=(d, l))
p.start()
p_list.append(p)
for res in p_list:
res.join() # 等待所有子进程执行完
print(d) #打印字典d
print(l) #打印列表l
进程同步
#coding:utf-8
from multiprocessing import Process, Lock
def f(l, i):
l.acquire() #加锁
try:
print('hello world', i)
finally:
l.release() #释放锁
print i
if __name__ == '__main__':
lock = Lock()
for num in range(10):
Process(target=f, args=(lock, num)).start()
进程池
进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。
进程池中有两个方法:
- apply 进程串行
- apply_async 进程并行
from multiprocessing import Process,Pool
import time,os
def Foo(i):
time.sleep(2)
print 'foo is', os.getpid()
return i+100
def Bar(arg):
print('-->exec done:',os.getpid())
if __name__=='__main__': #windows 必须加
pool = Pool(3) #运行进程池同时放进3个数据
for i in range(10):
pool.apply_async(func=Foo, args=(i,),callback=Bar) #callback回调,执行完foo,再调用Bar
#pool.apply(func=Foo, args=(i,))
print('end',os.getpid())
pool.close()
pool.join()#进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。
结果:
('end', 22868)
foo is 10768
('-->exec done:', 22868)
foo is 22060
('-->exec done:', 22868)
foo is 23728
('-->exec done:', 22868)
foo is 10768
('-->exec done:', 22868)
foo is 22060
('-->exec done:', 22868)
foo is 23728
('-->exec done:', 22868)
foo is 10768
('-->exec done:', 22868)
foo is 22060
('-->exec done:', 22868)
foo is 23728
('-->exec done:', 22868)
foo is 10768
('-->exec done:', 22868)