python-线程与进程

paramiko模块

  基于SSH用于远程连接服务器并执行相关操作,paramiko.SSHClient()

  通过scp可以传输文件,python基于scp来发送命令,paramiko.Transport(('hostname', port))

 1 import paramiko
 2 
 3 ssh = paramiko.SSHClient()                                  # 实例化ssh对象
 4 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())   # 允许连接不在know_hosts文件中的主机
 5 ssh.connect(hostname='bejsrtl200.bj.intel.com', username='jiawenyx', password='intel@7128') # 连接服务器
 6 stdin, stdout, stderr = ssh.exec_command('ifconfig')        # 执行命令
 7 
 8 print(stdout.read().decode())                               # 打印执行结果
 9 
10 ssh.close()
SSHClient
 1 import paramiko
 2 
 3 transport = paramiko.Transport(('bejsrtl184.bj.intel.com', 22))
 4 transport.connect(username='jiawenyx', password='intel@7128')
 5 
 6 ssh = paramiko.SSHClient()
 7 ssh._transport = transport
 8 
 9 stdin, stdout, stderr = ssh.exec_command('ifconfig')
10 print(stdout.read().decode())                               # 打印执行结果
11 
12 transport.close()
Transport
1 import paramiko
2 transport = paramiko.Transport(('host',22))
3 transport.connect(username='root',password='123')
4 sftp = paramiko.SFTPClient.from_transport(transport)
5 sftp.put('D:\Pycharm\hadoop_spark\ssh_files\id_rsa','/usr/local/id_rsa') # 文件名必须写上
6 transport.close()
SFTP

进程

进程和程序:

程序:指令的集合。

进程:是一个执行中的程序,即将程序装载到内存中,系统为它分配资源的这一过程。进程是操作系统资源分配的基本单位。

区别:程序是进程运行的静态描述文本,进程是程序的一次执行活动,属于动态概念。程序和进程无一一对应关系,一个程序可由多个进程共用,一个进程在活动中又可顺序地执行若干个程序。进程是一个能独立运行的单位,能与其他进程并发执行,进程是作为资源申请和调度单位存在的;而通常的程序段不能作为一个独立运行的单位。

   进程

每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。

   进程状态

    

线程

线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。

一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

python不管PC有几核,在同一核同一时刻执行的线程只有一个,python是调用系统的原生线程。

线程和进程的区别

  进程要操作CPU,必须要先创建一个线程,所有在同一个进程里的线程是共享同一块内存空间的;

线程共享内存空间,进程的内存是独立的;

同一个进程的线程之间可以直接交流,两个进程想通信,必须通过一个中间代理来实现;

创建新线程很简单, 创建新进程需要对其父进程进行一次克隆;

一个线程可以控制和操作同一进程里的其他线程,但是进程只能操作子进程;

threading模块

线程两种调用方式:

直接调用

 1 import threading
 2 import time
 3 
 4 
 5 def run(*args):           # 线程要运行的函数
 6 
 7     print('test',args)
 8     time.sleep(3)
 9 
10 
11 t1 = threading.Thread(target=run, args=('t1',))
12 t2 = threading.Thread(target=run, args=('t2',))
13 t1.start()
14 t2.start()
15 
16 print(t1.getName())
17 print(t2.getName())
18 # Thread-1
19 # Thread-2

继承式调用

 1 class MyThread(threading.Thread):
 2 
 3     def __init__(self, n ):
 4         super(MyThread, self).__init__()
 5         self.n = n
 6 
 7     def run(self):                # 必须写run函数
 8         print(self.n)
 9         time.sleep(2)
10 
11 t1 = MyThread('t1')
12 t2 = MyThread('t2')
13 t1.start()
14 t2.start()
15 
16 print(t1.getName())
17 print(t2.getName())

线程的一些方法

t.join(n)       表示主线程等待子线程多少时间,n表示主线程等待子线程的超时时间,如果在n时间内子线程未完成,主线程不在等待,执行后面的代码
t.run()         线程被cpu调度后自动执行线程对象的run方法(一般我们无需设置,除非自己定义类调用)
t.start()       线程准备就绪,等待CPU调度
t.getName()     获取线程的名称
t.setName()     设置线程的名称 
t.name          获取或设置线程的名称
t.is_alive()    判断线程是否为激活状态
t.isAlive()     判断线程是否为激活状态
t.isDaemon()    判断是否为守护线程
t.setDaemon()   是否设置守护线程,True表示主线程不等待子线程全部完成就执行后面的代码,False默认值,标识主线程等待子线程全部执行完后继续执行后面的代码

   threading.current_thread()     当前线程详细信息

   threading.active_count()  当前活跃线程数

  threading.get_ident     获得线程号

线程运行顺序

主线程启动子线程后,两者之间运行是并行的,默认主线程不会等待子线程运行结束,创建完成后继续往下执行,执行完后等待子线程全部执行完后退出程序。

 1 import threading
 2 import time
 3 
 4 
 5 def run(*args):           # 线程要运行的函数
 6 
 7     print('test',args)
 8     time.sleep(3)
 9     print(args, 'is done')
10 
11 start_time = time.time()
12 for i in range(10):
13     t = threading.Thread(target=run, args=('t-%s' %i ,))
14     t.start()
15 
16 print("-------------------------------------------")
17 print('run_time = ', time.time()- start_time)
18 
19 # test ('t-0',)
20 # test ('t-1',)
21 # test ('t-2',)
22 # test ('t-3',)
23 # test ('t-4',)
24 # test ('t-5',)
25 # test ('t-6',)
26 # test ('t-7',)
27 # test ('t-8',)
28 # test ('t-9',)
29 # -------------------------------------------
30 # run_time =  0.0
31 # ('t-3',) is done
32 # ('t-2',) is done
33 # ('t-1',) is done
34 # ('t-0',) is done
35 # ('t-6',) is done
36 # ('t-5',) is done
37 # ('t-4',) is done
38 # ('t-7',) is done
39 # ('t-8',) is done
40 # ('t-9',) is done
thread_no_join

  加入join,主线程会等待子线程执行完毕后继续往下执行,如果主线程需要子线程的返回结果,可以使用join。

 1 import threading
 2 import time
 3 
 4 
 5 def run(*args):           # 线程要运行的函数
 6     print('running',args)
 7     time.sleep(3)
 8     print(args, 'is done')
 9 
10 
11 start_time = time.time()
12 thread_pool = []
13 for i in range(10):
14     t = threading.Thread(target=run, args=('t-%s' %i ,))
15     t.start()
16     thread_pool.append(t)
17 
18 for i in thread_pool:
19     i.join()
20 
21 print('------------------------------------------')
22 
23 print('run_time = ', time.time()- start_time)
24 # 
25 # running ('t-0',)
26 # running ('t-1',)
27 # running ('t-2',)
28 # running ('t-3',)
29 # running ('t-4',)
30 # running ('t-5',)
31 # running ('t-6',)
32 # running ('t-7',)
33 # running ('t-8',)
34 # running ('t-9',)
35 # ('t-1',) is done
36 # ('t-0',) is done
37 # ('t-9',) is done
38 # ('t-8',) is done
39 # ('t-7',) is done
40 # ('t-6',) is done
41 # ('t-5',) is done
42 # ('t-4',) is done
43 # ('t-3',) is done
44 # ('t-2',) is done
45 # ------------------------------------------
46 # run_time =  3.0156748294830322
thread_join

join 参数:timeout      # 有n个设置join的子线程,就等待n倍timeout, 默认一直等待执行完毕

  当没有设置守护线程时,主线程等待N 倍timeout后继续往下执行, 主线程执行完毕,子线程依然可以继续执行,执行完毕后退出程序;对于守护线程则是到时间就kill子线程。

 1 import threading
 2 import time
 3 def run(*args):           # 线程要运行的函数
 4     print('running',args)
 5     time.sleep(3)
 6     print(args, 'is done')
 7 
 8 start_time = time.time()
 9 thread_pool = []
10 for i in range(5):
11     t = threading.Thread(target=run, args=('t-%s' %i ,))
12     t.setDaemon(True)
13     t.start()
14     thread_pool.append(t)
15 
16 for i in thread_pool:
17     i.join(0.5)           # 有n个线程就等待n 倍的timeout
18 
19 print('------------------------------------------')
20 
21 print('run_time = ', time.time()- start_time)
22 
23 #
24 # running ('t-0',)
25 # running ('t-1',)
26 # running ('t-2',)
27 # running ('t-3',)
28 # running ('t-4',)
29 # ------------------------------------------
30 # run_time =  2.531254768371582
31 #
32 # Process finished with exit code 0
join_timeout1
 1 import threading
 2 import time
 3 def run(*args):           # 线程要运行的函数
 4     print('running',args)
 5     time.sleep(3)
 6     print(args, 'is done')
 7 
 8 start_time = time.time()
 9 thread_pool = []
10 for i in range(5):
11     t = threading.Thread(target=run, args=('t-%s' %i ,))
12     t.setDaemon(True)
13     t.start()
14     thread_pool.append(t)
15 
16 for i in thread_pool:
17     i.join(0.6)           # 有n个线程就等待n 倍的timeout
18 
19 print('------------------------------------------')
20 
21 print('run_time = ', time.time()- start_time)
22 
23 # #running ('t-0',)
24 # running ('t-1',)
25 # running ('t-2',)
26 # running ('t-3',)
27 # running ('t-4',)
28 # ('t-2',) is done
29 # ('t-1',) is done
30 # ('t-0',) is done
31 # ('t-4',) is done
32 # ('t-3',) is done
33 # ------------------------------------------
34 # run_time =  3.021475076675415
35 # 
36 # Process finished with exit code 0
join_timeout2

守护线程

  为主线程服务,主线程退出,不必等待守护线程的结束。

  t.setDaemon(True)       把当前线程设置成守护线程 ,在t.start()之前设置

  由守护线程创建的子线程为守护线程,可以通过t.isDaemon来判断,详见代码 主线程_守护线程_子线程为什么会由守护线程创建的线程会直接退出。

 1 import threading
 2 import time
 3 
 4 
 5 def run(*args):           # 线程要运行的函数
 6 
 7     print('test',args)
 8     time.sleep(3)
 9     print(args, 'is done')
10 
11 start_time = time.time()
12 for i in range(10):
13     t = threading.Thread(target=run, args=('t-%s' %i ,))
14     t.setDaemon(True)
15     t.start()
16 
17 print("-------------------------------------------")
18 print('run_time = ', time.time()- start_time)
19 # 
20 # test ('t-0',)
21 # test ('t-1',)
22 # test ('t-2',)
23 # test ('t-3',)
24 # test ('t-4',)
25 # test ('t-5',)
26 # test ('t-6',)
27 # test ('t-7',)
28 # test ('t-8',)
29 # test ('t-9',)
30 # -------------------------------------------
31 # run_time =  0.0
32 # 
33 # Process finished with exit code 0
setDaemon
 1 import time
 2 import threading
 3 
 4 
 5 def run(n):
 6     print('[%s]------running----\n' % n)
 7     time.sleep(1)
 8     print('[%s]------done----\n' % n)
 9 
10 
11 def main():
12     for i in range(3):
13         t = threading.Thread(target=run, args=[i, ])
14         t.start()
15         t.join(0.5)
16         print('starting thread', t.getName())
17 
18 
19 m = threading.Thread(target=main, args=[])
20 m.setDaemon(True)  # 将main线程设置为Daemon线程,它做为程序主线程的守护线程,当主线程退出时,m线程也会退出,由m启动的其它子线程会同时退出,不管是否执行完任务
21 m.start()
22 m.join(timeout=3)
23 print("---main thread done----")
24 
25 
26 # Running result
27 # [0]------running----
28 # 
29 # starting thread Thread-2
30 # [1]------running----
31 # 
32 # starting thread Thread-3
33 # [0]------done----
34 # 
35 # [2]------running----
36 # 
37 # starting thread Thread-4
38 # [1]------done----
39 # 
40 # ---main thread done----
41 # 
42 # Process finished with exit code 0
主线程_守护线程_子线程

GIL: Global Interpreter Lock

  无论你启多少个线程,你有多少个cpu, Python在执行的时候会淡定的在同一时刻只允许一个线程运行。

GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念,同样一段代码可以通过CPython,PyPy,Psyco等不同的Python执行环境来执行。像其中的JPython就没有GIL。然而因为CPython是大部分环境下默认的Python执行环境。GIL并不是Python的特性,Python完全可以不依赖于GIL。

  GIL对python多线程的影响: http://www.dabeaz.com/python/UnderstandingGIL.pdf 

 线程锁(互斥锁Mutex)  

      线程锁保证同一时刻只有一个线程修改内存空间的同一数据,GIL保证同一时刻只有一个线程在运行。

  多线程同时修改同一数据,可能会导致数据最终结果不准确。

 1 import time
 2 import threading
 3 
 4 
 5 def addNum():
 6     global num  # 在每个线程中都获取这个全局变量
 7     time.sleep(1)
 8     num -= 1  # 对此公共变量进行-1操作
 9     print('%s--get num:%s:'%(threading.current_thread().name,num ))
10 
11 num = 5 # 设定一个共享变量
12 thread_list = []
13 for i in range(5):
14     t = threading.Thread(target=addNum)
15     t.start()
16     thread_list.append(t)
17 
18 for t in thread_list:  # 等待所有线程执行完毕
19     t.join()
20 
21 print('final num:', num)
多线程修改同一数据

  如果需要多个线程去修改同一数据,则需要给数据加一个线程锁。python3.x不加锁也不会出问题,但是建议加。如果修改数据量比较大的话,容易产生串行。

 1 import time
 2 import threading
 3 
 4 
 5 lock = threading.Lock()
 6 def addNum():
 7 
 8     lock.acquire()
 9     global num  # 在每个线程中都获取这个全局变量
10     time.sleep(1)
11     num -= 1  # 对此公共变量进行-1操作
12     print('%s--get num:%s'%(threading.current_thread().name,num ))
13     lock.release()
14 
15 num = 5 # 设定一个共享变量
16 thread_list = []
17 for i in range(5):
18     t = threading.Thread(target=addNum)
19     t.start()
20     thread_list.append(t)
21 
22 for t in thread_list:  # 等待所有线程执行完毕
23     t.join()
24 
25 print('final num:', num)
threading.Lock

 递归锁

一个锁里面包含了子锁。

 1 import time
 2 import threading
 3 
 4 
 5 lock = threading.RLock()
 6 def run2():
 7     global num2
 8     lock.acquire()
 9     num2 -= 1
10     lock.release()
11 
12 
13 def addNum():
14     global num1 # 在每个线程中都获取这个全局变量
15     lock.acquire()
16     run2()
17     time.sleep(1)
18     num1 -= 1  # 对此公共变量进行-1操作
19     print('%s--get num1:%s,num2:%s'%(threading.current_thread().name,num1,num2))
20     lock.release()
21 
22 num1, num2 = 5, 9 # 设定一个共享变量
23 thread_list = []
24 for i in range(5):
25     t = threading.Thread(target=addNum)
26     t.start()
27     thread_list.append(t)
28 
29 
30 while threading.active_count() != 1:
31     print(threading.active_count())
32     time.sleep(1)
33 else:
34     print('----all threads done---')
35 print('final num:', num1, num2)
RLock

 信号量:Semaphore

互斥锁允许同一时刻只有一个线程修改数据,Semaphore 允许同一时刻运行一定数量的线程。

 1 import time
 2 import threading
 3 
 4 
 5 semaphore = threading.BoundedSemaphore(3)
 6 
 7 def addNum():
 8     semaphore.acquire()
 9     time.sleep(1)
10     print('%s---running'%threading.current_thread().name)
11     semaphore.release()
12 
13 for i in range(10):
14     t = threading.Thread(target=addNum)
15     t.start()
16 
17 
18 while threading.active_count() != 1:
19     pass
20 else:
21     print('----all threads done---')
Semaphore

Events

 红绿灯,一个线程充当交通指挥灯,多个线程充当车辆,按照红灯停绿灯行的规则。

 注意event.set, event.clear放在打印灯和车的状态位置,否则容易出现红灯车也在跑的情况。

 1 import threading, time, random
 2 
 3 
 4 events = threading.Event()
 5 
 6 def lighter():
 7     if not events.isSet():
 8         events.set()                        # 初始化绿灯Event set
 9     counter = 0
10     while True:
11         if counter < 5:
12             print('\033[42;0mGreen is lighten...\033[0m')
13         elif counter < 10:
14             if events.isSet():
15                 events.clear()
16             print('\033[41;0mRed is lighten...\033[0m')
17 
18         else:
19             counter = 0
20 
21             print('\033[42;1m--green light on---\033[0m')
22             events.set()
23         time.sleep(1)
24         counter += 1
25 
26 def car(i):
27     while True:
28         if events.isSet():
29             print("car[%s] is running..."%i)
30             time.sleep(random.randrange(10))
31         else:
32             print('car is waiting green lighten...')
33             events.wait()
34 if __name__ == '__main__':
35     lighter1 = threading.Thread(target=lighter)
36     lighter1.start()
37     for i in range(3):
38         t = threading.Thread(target=car, args=(i,))
39         t.start()
交通灯

 Event对象通过设置/清除标志位来实现和其他线程的同步,例如交通灯来修改Event的标志位来控制车辆线程的状态。

 Event的几大方法:

  event.set:                          设置标志位为True

  event.clear:       清除标志位,标志位为False

  event.wait:        如果标志位为True,则不做操作;否则一直阻塞至标志位被设置为True

  event.isSet:      相当于event.is_set,如果标志位被设置,则返回True;否则返回False

 queue 队列

class queue.Queue(maxsize=0)             # 先入先出
class queue.LifoQueue(maxsize=0)        # 后入先出
class queue.PriorityQueue(maxsize=0)  # 按设置优先级获取数据

maxsize代表队列最多能存放的条目数,一旦达到maxsize队列将会阻塞,直到队列被被使用;0或者负数表示队列无穷大。
优先级原则:最低值的条目是先检索的,最低值的条目是排序后返回的条目(列表(条目))[0]。条目的典型模式是表单中的元组:(priority_number, data)。

Queue.qsize()                    #  返回队列大小
Queue.empty()                #  如果队列为empty,则返回True
Queue.full()                     #  如果队列为full,则返回True

Queue.put(item, block=True, timeout=None)

将item插入队列,默认block为True, timeout为None,如果队列为full,则会阻塞知道队列条目被get。
如果timeout是一个正数,将会等待timeout 秒,队列仍然为full,则抛出Full exception;
如果block为false, 队列为full, 此时向队列插入数据时,直接抛出Full exception, 即使timeout设置为正数也将会被忽略。

   Queue.put_nowait(item) 等价于 put(item, False)

Queue.get(block=True, timeout=None)

从队列中获取数据或者删除队列书中的数据,默认block为True,timeout为None,如果队列为空,则会阻塞直到队列为非空。
如果timeout是一个正数,将会等待timeout 秒,队列仍然为空,则抛出Empty exception;
如果block为false,队列为空,此时从队列获取数据时,直接抛出Empty exception,即使timeout设置为正数也将会被忽略。

Queue.get_nowait() 等价于 get(False)

exception queue.Empty  

exception queue.Full

Queue.task_done()                       

Queue.join()                                   block直到queue被消费完毕

 https://docs.python.org/3.5/library/queue.html#queue.Queue.task_done

多线程的应用

python多线程不适合cpu密集操作型任务,适合io操作密集型的任务。

io操作不占用cpu,计算占用cpu。

多进程

  多进程的定义和多线程类似。每个进程都拥有一个独立的内存空间,所以多进程需要较大的开销。

 1 from multiprocessing import Process
 2 import os
 3 
 4 def run(i):
 5 
 6     print('number: %s, process id: %s, parent id: %s, moudle name: %s'%
 7           (i, os.getpid(),os.getppid(),__name__))
 8 
 9 p_num = []
10 if __name__ == '__main__':     # 多进程win 系统需要加这句,否则报错
11     for i in range(10):
12         p = Process(target=run, args=(i,))
13         p.start()
14         p_num.append(p)
15     for p in p_num:
16         p.join()               # 和多线程功能一样
17 
18     print('main is done, moudle name: %s'%__name__)
number: 0, process id: 988, parent id: 25368, moudle name: __mp_main__
number: 1, process id: 5240, parent id: 25368, moudle name: __mp_main__
number: 3, process id: 21328, parent id: 25368, moudle name: __mp_main__
number: 2, process id: 24892, parent id: 25368, moudle name: __mp_main__
number: 4, process id: 25276, parent id: 25368, moudle name: __mp_main__
number: 5, process id: 24612, parent id: 25368, moudle name: __mp_main__
number: 7, process id: 12340, parent id: 25368, moudle name: __mp_main__
number: 6, process id: 24464, parent id: 25368, moudle name: __mp_main__
number: 8, process id: 20040, parent id: 25368, moudle name: __mp_main__
number: 9, process id: 20796, parent id: 25368, moudle name: __mp_main__
main is done, moudle name: __main__

Process finished with exit code 0
run_result

进程间通信

同一进程内的线程共享进程内存空间,可以直接访问同一数据;不同进程都拥有一个独立内存空间,要想实现两个进程间的数据交换,可通过以下方法:

 Queue   

  使用方法和线程queue一样,线程中的queue不能实现进程中的数据通信。

 1 from multiprocessing import Process, Queue
 2 import os
 3 
 4 def run(q):
 5 
 6     print('process id: %s'% os.getpid())
 7     q.put(os.getpid())
 8 
 9 p_num = []
10 if __name__ == '__main__':     # 多进程win 系统需要加这句,否则报错
11     q = Queue()
12     for i in range(10):
13         p = Process(target=run, args=(q,))
14         p.start()
15         p_num.append(p)
16     for p in p_num:
17         p.join()               # 和多线程功能一样
18 
19     for i in range(10):
20         print('main is done, q = %s'% q.get())
Queue
process id: 12976
process id: 27556
process id: 11424
process id: 28284
process id: 29056
process id: 14728
process id: 22856
process id: 26928
process id: 28496
process id: 6612
main is done, q = 27556
main is done, q = 12976
main is done, q = 11424
main is done, q = 28284
main is done, q = 29056
main is done, q = 14728
main is done, q = 22856
main is done, q = 26928
main is done, q = 28496
main is done, q = 6612

Process finished with exit code 0
result

Pipe

  由Pipe()返回的两个连接对象表示管道的两端,每个连接对象都有send()和recv()方法。

     注意,如果两个进程(或线程)试图同时读取或写入管道的同一端口,那么管道中的数据可能会被损坏;在同时使用不同端口的过程中也不会有风险。

 1 from multiprocessing import Process, Pipe
 2 import  os
 3 
 4 
 5 
 6 def run(conn):
 7     conn.send('process id: %s'%os.getpid())
 8     conn.send('process done')
 9     conn.close()
10     print('child process id: %s'% os.getpid())
11 
12 
13 if __name__ == '__main__':
14     parent_conn, child_conn = Pipe()
15     p = Process(target=run, args=(child_conn,))
16     p.start()
17     print(parent_conn.recv())
18     print(parent_conn.recv())
19 # child process id: 10816
20 # process id: 10816
21 # process done

Manager

Manager 支持list, dict, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event, Barrier, Queue, Value and Array等数据类型。

 1 from multiprocessing import Process, Manager
 2 import os
 3 
 4 def f(d, l):
 5     d['%s parent is %s'%(os.getpid(), os.getppid())] = os.getppid()
 6     l.append(os.getpid())
 7 
 8 
 9 
10 if __name__ == '__main__':
11     with Manager() as manager:
12         d = manager.dict()
13         l = manager.list(range(3))
14         p_list = []
15         for i in range(5):
16             p = Process(target=f, args=(d, l))
17             p.start()
18             p_list.append(p)
19         for res in p_list:
20             res.join()
21 
22         print(list(d.keys()))    # 以list类型返回字典的key
23         print(l)
24         
25 # ['26500 parent is 29096', '23932 parent is 29096', '29540 parent is 29096', '27728 parent is 29096', '15348 parent is 29096']
26 # [0, 1, 2, 26500, 27728, 15348, 23932, 29540]

进程同步:进程锁

进程锁用来锁定输出,否则容易混淆,比如一个进程输出没完,另一个进程继续输出。

 1 from multiprocessing import Process, Lock
 2 
 3 
 4 def f(l, i):
 5     l.acquire()
 6     print('hello world', i)
 7     l.release()
 8 
 9 if __name__ == '__main__':
10     lock = Lock()
11 
12     for num in range(10):
13         Process(target=f, args=(lock, num)).start()

进程池

进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进程,那么程序就会等待,直到进程池中有可用进程为止。

  • apply                    从进程池中获取的进程串行运行
  • apply_async   从进程池中获取的进程并行运行
 1 from multiprocessing import Pool
 2 import time, os
 3 
 4 
 5 def f1(arg):
 6     time.sleep(1)
 7     print('process id %s:'%os.getppid(),arg)
 8     return arg     # 传给Bar
 9 
10 def Bar(args):      # 由父进程执行
11     print('%s execute %s'%(os.getppid(),args))
12 
13 
14 
15 if __name__ == '__main__':
16     pool = Pool(5)
17     for i in range(10):
18         # pool.apply(func=f1,args=(i,))       # 所有进程串行执行
19         pool.apply_async(func=f1, args=(i,), callback=Bar)  # 异步并行执行
20 
21     pool.close()                         # 等待所有的任务执行完毕
22 
23     # pool.terminate()                  # 立即终止子进程的任务,主进程继续执行
24     pool.join()  # 执行pool.join时必须先执行pool.close或者pool.terminate
25     # 进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭close,terminate也无效
26     print('end')
27 
28 # process id 8360: 0
29 # 19884 execute 0
30 # process id 8360: 1
31 # 19884 execute 1
32 # process id 8360: 2
33 # 19884 execute 2
34 # process id 8360: 3
35 # 19884 execute 3
36 # process id 8360: 4
37 # 19884 execute 4
38 # process id 8360: 5
39 # 19884 execute 5
40 # process id 8360: 6
41 # 19884 execute 6
42 # process id 8360: 7
43 # 19884 execute 7
44 # process id 8360: 8
45 # 19884 execute 8
46 # process id 8360: 9
47 # 19884 execute 9
48 # end
49 # 
50 # Process finished with exit code 0

猜你喜欢

转载自www.cnblogs.com/gareth-yu/p/8887969.html
今日推荐