进程/线程池/进程ID/进程间的通讯pipe/Queue/Manager/进程同步
1 # 1.线程和进程的区别? 2 # 进程 -> 资源的集合 3 # 线程 -> 操作cpu的最小调度单位 4 # 进程和线程谁快? 无法比 5 # 进程至少包含一个线程,进程需要靠线程启动 6 # 线程之间内存是共享的,线程同时修改同一份数据时需要加锁 互斥锁 7 # 递归锁->锁中有锁 8 # 2.join等待线程执行结束 启动线程的语法 9 # def run(): 10 # ... 11 # t_joins = [] 12 # for i in range(10): 13 # t = threading.Thread(target=run, args("arg", )) 14 # t_joins.append(t) 15 # t.start() 16 # for t in t_joins: 17 # t.join() #等待线程执行结束,线程之间是独立运行的 18 # 3.守护线程: 19 # for i in range(10): 20 # t = threading.Thread(target=run, args("arg", )) 21 # t.setDaemon(True) #设置守护线程 22 # t.start() 23 # 4.队列: 24 # 解耦,使程序松耦合 25 # 提高运行效率 26 # queue.Queue#FIFO 27 # queue.LifoQueue#last come first out 28 # queue.PriorityQueue 29 # 生产者消费者模型->解耦 30 # 5.事件 Event 31 # 32 # 6.python的多线程是利用了cpu上下文切换的优势:单线程上下文切换 33 # io操作不占用cpu : 读取数据 34 # 计算占用cpu : 35 # 线程的切换需要来回切换上下文,python的多线程不适合cpu密集型操作的任务,适合io操作密集的任务 36 # 37 # 7.多进程:进程之间无GIL概念 数据不可共享 是相互独立的 ->折中的解决 38 # 八核->同一时间同时只能做八个任务(进程) 39 # 40 41 ####################################################################################### 42 # 1.如何开启一段进程 43 # import multiprocessing 44 # import time,threading 45 # 46 # def thread_run(): 47 # print(threading.get_ident()) #获取当前线程号 48 # 49 # def run(n): 50 # print("start processing %s" % n) 51 # t = threading.Thread(target=thread_run) 52 # t.start() 53 # # time.sleep(1) 54 # if __name__ == "__main__": 55 # for i in range(10): 56 # process = multiprocessing.Process(target=run, args=("进程%s" %i, )) 57 # process.start() 58 # # process.join() 59 60 ####################################################################################### 61 # 2.如何获取进程ID 62 # from multiprocessing import Process 63 # import os 64 # def info(title): 65 # print(title) 66 # print("module name:", __name__) 67 # print("parent process,", os.getppid()) 68 # print("process id", os.getpid()) 69 # print("\n\n") 70 # 71 # def f(name): 72 # info('\033[31;1mfunction\033[0m') 73 # print('hello', name) 74 # 75 # if __name__ == '__main__': 76 # info('\033[32;1mmain process line\033[0m') 77 # p = Process(target=f, args=('bob',)) 78 # p.start() 79 # p.join() 80 81 ####################################################################################### 82 # 3.进程间如何通讯 83 # 3.1 Queue形式 84 # from multiprocessing import Process, Queue 85 # import threading, queue 86 # 87 # def f(q): 88 # q.put([42, None, 'hello']) 89 # 90 # if __name__ == '__main__': 91 # '''进程间的queue 数据共享''' 92 # q = Queue() 93 # p = Process(target=f, args=(q,)) 94 # '''线程间的数据共享''' 95 # # q = queue.Queue() 96 # # p = threading.Thread(target=f, args=(q,)) 97 # '''进程间数据不能用线程间共享''' 98 # # q = queue.Queue() 99 # # p = Process(target=f, args=(q,)) 100 # p.start() 101 # print(q.get()) # prints "[42, None, 'hello']" 102 # p.join() 103 # # 进程间的数据共享和线程间的数据共享不是一回事 线程间的数据共享是同一份数据 进程间的数据共享其实是通过pikle序列化和反序列化克隆后的结果 104 # 3.2管道形式 pipe 105 # from multiprocessing import Process, Pipe 106 # 107 # def f(conn): 108 # conn.send([42, None, 'hello from child']) 109 # conn.send([42, None, 'hello from child']) 110 # conn.close() 111 # 112 # if __name__ == '__main__': 113 # parent_conn, child_conn = Pipe() #管道两遍分别交给两边 114 # p = Process(target=f, args=(child_conn,)) 115 # p.start() 116 # print(parent_conn.recv()) # prints "[42, None, 'hello']" 117 # print(parent_conn.recv()) 118 # p.join() 119 120 # 3.3Manager完全同步(真正的共享,且不需要加锁,manager中已经加锁) 121 # from multiprocessing import Process, Manager 122 # import os 123 # 124 # def f(d, l): 125 # # d[1] = '1' 126 # # d['2'] = 2 127 # # d[0.25] = None 128 # # l.append(1) 129 # d[os.getpid()] = os.getpid() 130 # l.append(os.getpid()) 131 # print(l) 132 # 133 # if __name__ == '__main__': 134 # with Manager() as manager: #赋值变量 135 # d = manager.dict() #生成一个字典,可在多个进程间共享和传递 136 # 137 # l = manager.list(range(5)) #生成列表,可在多个进程间共享和传递 138 # p_list = [] 139 # for i in range(10): 140 # p = Process(target=f, args=(d, l)) 141 # p.start() 142 # p_list.append(p) 143 # for res in p_list: #等待结果 144 # res.join() 145 # 146 # print(d) 147 # print(l) 148 149 # 3.4 进城同步 因为屏幕共享 控制屏幕打印不会乱 150 # 起一个进程相当于克隆一份父进程的数据 开销很大 151 # from multiprocessing import Process, Lock 152 # 153 # def f(l, i): 154 # l.acquire() 155 # try: 156 # print('hello world', i) 157 # finally: 158 # l.release() 159 # 160 # if __name__ == '__main__': 161 # lock = Lock() 162 # 163 # for num in range(10): 164 # Process(target=f, args=(lock, num)).start() 165 166 ####################################################################################### 167 # 4.进程池 避免进程太多 开销太大 168 # apply:串行 169 # apply_async:并行 170 # from multiprocessing import Process, Pool 171 # import time,os 172 # 173 # def Foo(i): 174 # time.sleep(2) 175 # print("in process ",os.getpid()) 176 # return i + 100 177 # 178 # def Bar(arg): 179 # print("子进程中pid:", os.getpid()) 180 # print('-->exec done:', arg) #回调函数是父进程调用的 可以避免子进程的多次连接数据库等等 提高效率 181 # if __name__ == "__main__": #为了区分你是主动执行这个脚本还是通过模块去调用 手动执行脚本 __name__为main 用模块调用则是模块名 测试用 182 # pool = Pool(processes=5) #允许进程池同时放入五个进程 多余的将会排队不会被执行 183 # print("主进程中pid:",os.getpid()) 184 # for i in range(10): 185 # pool.apply_async(func=Foo, args=(i,), callback=Bar) #callback回调执行完后执行 186 # # pool.apply(func=Foo, args=(i,)) #往进程池里放一个进程 187 # 188 # pool.close() 189 # pool.join() # 进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。 190 # print('end')