python学习道路(day10note)(线程,进程)
1.计算机的发展史
看alex的博客吧,了解一下可以了
2.线程与GIL简介
#线程 #一道单一的指令的控制流,寄生在进程中 #单一进程里的多个线程是共享数据的 #多个线程涉及修改共享数据的时候需要枷锁,看的时候不需要 #GIL global interperter lock 全局锁 #有多少个cpu,启动多少个线程,python执行的时候只会在同一时刻只允许一个线程运行
3.多线程的写法
#多线程代码 简单 # import threading # import time # def run(n): # time.sleep(1) # print('thread>>>:',n) # # t1 = threading.Thread(target=run,args=(1,)) #分支线程 # t1.start() # print('----------------fengexian') #主线 因为主线更快,所以先显示 # t2 = threading.Thread(target=run,args=(2,))#分之线程 # t2.start() #多线程代码 并发量高 # print("多线程代码 并发量高") # import threading # import time # def run(n): # time.sleep(1) # print('thread>>>:',n) # for i in range(10): # t = threading.Thread(target=run,args=(i,)) # t.start() #多线程代码里面一些常用语句 # import threading # import time # def run(n): # time.sleep(1) # print(threading.get_ident()) #可以理解一个线程号,但是在该线程中唯一的,但是在系统中不一定唯一 # print('thread>>>:',n) # print(threading.current_thread()) 打印当前正在运行线程的实例 # for i in range(10): # t = threading.Thread(target=run,args=(i,)) # t.start() # t.setName("t-"%i) 更改线程名 # print(t.getName()) #线程名 # print(threading.active_count()) #活跃的线程数统计 # print(threading.current_thread()) 打印主线程的实例 #主线程死了相当于程序退出了,其他的线程是平行的。所以没关系
4.通过类的方式继承启用多线程
#通过类的方式继承启用多线程 一般不这么写 # print("#通过类的方式继承启用多线程") # 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()
5.线程等待,就是主线程需要等待分支线程结束才继续执行
#线程等待 # import threading # import time # def run(n): # time.sleep(1) # print("thread:::",n) # a_list = [] # for i in range(10): # a = threading.Thread(target=run,args=(i,)) # a.start() # a_list.append(a) # # a.join() #相当于串行 但是我需要线程都结束才走主线程 # for a in a_list: # a.join() #把等待线程结束放这里,相当于等待全部线程结束 # #必须用for循环,直接放在外面不能保证每个线程都执行完 # print("--main thread--")
6.守护线程,当主线程挂了,分支线程也会相应的结束
#主线程死了,线程就该停了 守护进程的概念 # import threading # import time # def run(n): # time.sleep(1) # print("thread:::",n) # for i in range(10): # a = threading.Thread(target=run,args=(i,)) # a.setDaemon(True) #设置为守护线程 当主线程执行完,不管线程结没结束都退出 # a.start() # print("--main thread--")
7.线程锁(普通锁LOCK,递归锁RLOCK),为了避免出现同时更改一个共享数据发生错乱
#线程锁 防止多个线程修改同一个共享数据 #一个进程下可以启动多个线程,多个线程共享父进程的内存空间,也就意味着每个线程可以访问同一份数据,此时,如果2个线程同时要修改同一份数据,会出现什么状况? #此代码没有出现混乱的问题,就是本来应该是10而显示只有 8 9 这个样子 #一定要加锁 # import threading # import time # def run(n): # global num # l.acquire() #获取锁 # num +=1 # time.sleep(1) #修改完数据之后,立刻就把锁释放,因为只要你一锁,只要全局需要等你的数据,就整个程序卡住了,就出现串行了 # l.release() #释放锁 # # time.sleep(1) #如果把这个放到释放锁上面,那就成为串行了。 # print("thread:::",n) # # def run2(): # count = 0 # while num<9: # print('-----',count) # count += 1 # # num = 0 # l = threading.Lock() #声明一把锁 # a_list = [] # for i in range(10): # a = threading.Thread(target=run,args=(i,)) # a.start() # a_list.append(a) # # a2 = threading.Thread(target=run2) # a2.start() # for t in a_list: # t.join() # # print("--main thread--") # print(num) #RLock(递归锁)就是在一个大锁中还要再包含子锁 # import threading, time # # def run1(): # print("grab the first part data") # lock.acquire() # global num # num += 1 # lock.release() # return num # # def run2(): # print("grab the second part data") # lock.acquire() # global num2 # num2 += 1 # lock.release() # return num2 # # def run3(): # lock.acquire() # res = run1() # print('--------between run1 and run2-----') # res2 = run2() # lock.release() # print(res, res2) # # if __name__ == '__main__': # # num, num2 = 0, 0 # lock = threading.RLock() #如果Rlock 换成lock 就会错乱了 # for i in range(10): # t = threading.Thread(target=run3) # t.start() # # while threading.active_count() != 1: # print(threading.active_count()) # else: # print('----all threads done---') # print(num, num2)
8.GIL全局解释其锁和用户级别的Lock的区别
#GIL VS LOCK #GIL 全局解释器锁,作用是保证在同一时刻只有一个线程真正在运行 #GIL 解释器自己的锁,为了解决内存回收机制,很有可能当内存清除的时候会有线程调用它才加的锁 #GIL 和用户Lock是不一样的锁,没有任何关系
9.信号量
# Semaphore(信号量) # 互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。 #改代码执行后结果为五个五个出 # import threading, time # def run(n): # semaphore.acquire() # time.sleep(1) # print("run the thread: %s\n" % n) # semaphore.release() # # if __name__ == '__main__': # # num = 0 # semaphore = threading.BoundedSemaphore(5) # 最多允许5个线程同时运行 # for i in range(20): # t = threading.Thread(target=run, args=(i,)) # t.start() # # while threading.active_count() != 1: # pass # print threading.active_count() # else: # print('----all threads done---') # print(num)
10.定时任务
#定时任务 Timer 3秒之后运行这个线程 # import threading # def hello(): # print("hello, world") # # t = threading.Timer(3.0, hello) # t.start() # after 30 seconds, "hello, world" will be printed
11.events 线程间的交互
#Events 线程间的交互 #通过Event来实现两个或多个线程间的交互,下面是一个红绿灯的例子,即起动一个线程做交通指挥灯,生成几个线程做车辆,车辆行驶按红灯停,绿灯行的规则。 #可以当做线程内部的一个标志,当这个标志发生变化,就说明该线程干完了 #红绿灯 # import threading,time # # def ligher(): # count = 0 # while True: # if count < 30: # if not event.is_set(): #如果没被set我就set # event.set() # print("\033[32m;green light\033[0m") # elif count < 34: # print("\033[33m;yellow light\033[0m") # elif count < 60: # if event.is_set(): # event.clear() # print("\033[31m;red light\033[0m") # else: # count = 0 # count += 1 # time.sleep(0.2) # def car(n): # count = 0 # while True: # event.wait() # print("car [%s] dududu..." % n) # count += 1 # time.sleep(1) # # event = threading.Event() # t = threading.Thread(target=ligher) # t.start() # c1 = threading.Thread(target=car,args=(1,)) # c1.start()
12.队列
#队列 Queue #先进先出 FIFO first in first out 常规 #后入先出 last in first out #不按顺序出,优先级 #先进先出队列 # import queue # q = queue.Queue() # q.put(1) # q.put(2) # q.put(3) # q.put('alex') # print(q.qsize()) #数量 # print(q.get()) #取数 # print(q.empty()) #做一个判断是不是空而已不是清空 # print(q.get()) # print(q.full()) #判断队列会不会满 如果满了,就会阻塞了,q = queue.Queue(maxsize=2),等于2的时候就会返回TRUE # q.put_nowait(4) #如果满了就直接报错了 #先进后出队列 # import queue # q = queue.LifoQueue() # q.put(1) # q.put(2) # q.put(3) # q.put('alex') # print(q.get()) #优先级队列 # import queue # q = queue.PriorityQueue() # q.put([3,'joker']) # q.put([2,'lili']) # q.put([1,'alex']) # print(q.get()) #1 2 3代表优先级,数字越小权重越大 列表,元祖都可以
13.生产者与消费者模型 就是为了解决供不应求,供过于求的时候
#生产者消费者模型 就是为了解决 线程产生和处理线程的速度不一致问题 #在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。 #为什么要使用生产者和消费者模式 #在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据 #同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。 #什么是生产者消费者模式 #生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。 #生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。 #吃骨头 #就是为了解决供不应求,供大于求,最大一个特点程序解耦合,添加生产者不会影响消费者,添加消费者不会影响生产者。提高程序运行效率 # import threading,time # import queue # def producer(name): # count = 0 # while True: # if q.qsize() < 5: # print("%s生成了骨头" %name,count) # q.put(count) # count+=1 # time.sleep(3) # # def consumer(n): # while True: # print("%s 取到骨头并吃了它" % n, q.get()) # time.sleep(0.5) # # q = queue.Queue(maxsize=4) # # p = threading.Thread(target=producer,args=('joker',)) # p2 = threading.Thread(target=producer,args=('alex',)) # c = threading.Thread(target=consumer,args=('lili',)) # p.start() # p2.start() # c.start() #消费完任务之后都要给生产者回执,当生产者回执都结束了,就可以结束了 例如发邮件 转账 # import threading,time # import queue # def producer(name): # count = 0 # for i in range(10): # print("%s生成了骨头" %name,count) # q.put(count) # count+=1 # time.sleep(0.3) # q.join() # print("所有骨头都被吃了") # def consumer(n): # while True: # print("%s 取到骨头并吃了它" % n, q.get()) # time.sleep(0.5) # q.task_done() # 代表我吃完了,就像邮件回执,代表你肯定吃了,肯定回执邮件,这个任务你干完了 # q = queue.Queue(maxsize=4) # p = threading.Thread(target=producer,args=('joker',)) # c = threading.Thread(target=consumer,args=('lili',)) # p.start() # c.start()
14.多进程
#多进程multiprocessing #绕过GIL 例子。八核八个进程,每个进程是个线程 # from multiprocessing import Process # import time # # def f(name): # time.sleep(2) # print('hello', name) # # if __name__ == '__main__': # for i in range(10): # p = Process(target=f, args=('bob',)) # p.start() # # p.join() #打开就是串行出来hello bob #多进程的用法 # from multiprocessing import Process # import os,time # def info(title): # print(title) # print('module name:', __name__) # print('parent process:', os.getppid()) #父id # print('process id:', os.getpid()) #当前Id # print("\n\n") # # def f(name): # info('\033[31;1mfunction f\033[0m') # print('hello', name) # time.sleep(10) # # if __name__ == '__main__': # info('\033[32;1mmain process line\033[0m') # p = Process(target=f, args=('bob',)) # p.start() # p.join()
15.进程间通讯,Queue,pipe 进程数据交互,并没有改变数据,真正可以改变数据的用manager
#进程间通讯 #不同进程间内存是不共享的,要想实现两个进程间的数据交换,可以用以下方法: #Queues 使用方法跟threading里的queue差不多 但是线程内存共享的,进程不行 # from multiprocessing import Process, Queue # # def f(q): # q.put([42, None, 'hello']) # # if __name__ == '__main__': # q = Queue() # p = Process(target=f, args=(q,)) # p.start() # print(q.get()) # prints "[42, None, 'hello']" # p.join() #Pipes 管道 儿子发,父亲收 当然也可以双向,2个进程间通信 # from multiprocessing import Process, Pipe # # def f(conn): # conn.send([42, None, 'hello']) #这里需要注意,发送数据多次没有什么问题,但是要是收的时候没有数据就会卡住 # 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']" # parent_conn.send("hello son") #双向 # p.join() #Queues 和 Pipe 解决了2个进程间的传递并没有解决2个进程之间修改数据 #Manager # from multiprocessing import Process, Manager # # def f(d, l,): #def f(d, l, n,): 加n为了字典效果 # # d[n] = n #为了字典效果 # d[1] = '1' # d['2'] = 2 # d[0.25] = None # l.append(2) #每次进程加个2 # #l.append(n) 为了字典效果 # print(l) # # if __name__ == '__main__': # with Manager() as manager: #打开manager # d = manager.dict() #生成一个字典 # # l = manager.list(range(5)) #就是生成了五个列表值 [0, 1, 2, 3, 4] # p_list = [] # for i in range(10): # p = Process(target=f, args=(d, l)) # # p = Process(target=f, args=(d, l, i,)) 为了字典效果 # p.start() # p_list.append(p) # # for res in p_list: # res.join() # # print(d) # print(l)
16.进程同步
#进程同步 就是Lock 进程数据独立为什么还需要锁呢 #因为共享一个屏幕,可能输出会乱,加了锁,输出显示就没问题,输入文件也要加锁 # from multiprocessing import Process, Lock # # def f(l, i): # l.acquire() # try: # print('hello world', i) # finally: # l.release() # # if __name__ == '__main__': # lock = Lock() # # for num in range(10): # Process(target=f, args=(lock, num)).start() 进程自己把锁传进去
17.进程池
进程池 就是同一时间只有多少个进程运行 #进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。 # 进程池中有两个方法: # apply 是串行 ,不要用 # apply_async # from multiprocessing import Process, Lock, Pool # import time # # def f(num): # print('hello world %s' % num) # time.sleep(1) # return num #返回值告诉主进程我子进程运行结束了么 # # def callback(data): #这个就是上面f函数的返回值 他的pid永远都是一个,所以只维护一个连接就可以 # print("exec-->:",data) # # if __name__ == '__main__': # lock = Lock() # # pool = Pool(processes=5) # # for num in range(100): # pool.apply_async(func=f, args=(num,),callback=callback) # pool.close() #添加完了必须告诉程序地址池我加完了 # pool.join() #进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。
18.paramiko 简单的ssh模块
#paramiko 模块 import paramiko # 创建SSH对象 ssh = paramiko.SSHClient() # 允许连接不在know_hosts文件中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #第一次连接在不在自己本机上,不在自己就加上去 # 连接服务器 ssh.connect(hostname=') # 执行命令 返回三个值 stdin, stdout, stderr = ssh.exec_command('df') # 获取命令结果 result = stdout.read() print(result.decode()) # 关闭连接 ssh.close()
python学习道路(day10note)(线程,进程)的更多相关文章
- python学习笔记12 ----线程、进程
进程和线程的概念 进程和线程是操作系统中两个很重要的概念,对于一般的程序,可能有若干个进程,每一个进程有若干个同时执行的线程.进程是资源管理的最小单位,线程是程序执行的最小单位(线程可共享同一进程里的 ...
- python学习笔记11 ----线程、进程、协程
进程.线程.协程的概念 进程和线程是操作系统中两个很重要的概念,对于一般的程序,可能有若干个进程,每一个进程有若干个同时执行的线程.进程是资源管理的最小单位,线程是程序执行的最小单位(线程可共享同一进 ...
- Python学习笔记9-多线程和多进程
一.线程&进程 对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程, ...
- python之并发编程(线程\进程\协程)
一.进程和线程 1.进程 假如有两个程序A和B,程序A在执行到一半的过程中,需要读取大量的数据输入(I/O操作),而此时CPU只能静静地等待任务A读取完数据才能继续执行,这样就白白浪费了CPU资源.是 ...
- python学习笔记之线程、进程和协程(第八天)
参考文档: 金角大王博客:http://www.cnblogs.com/alex3714/articles/5230609.html 银角大王博客:http://www.cnblogs.com/wup ...
- 4月27日 python学习总结 GIL、进程池、线程池、同步、异步、阻塞、非阻塞
一.GIL:全局解释器锁 1 .GIL:全局解释器锁 GIL本质就是一把互斥锁,是夹在解释器身上的, 同一个进程内的所有线程都需要先抢到GIL锁,才能执行解释器代码 2.GIL的优缺点: 优点: 保 ...
- python学习道路(day11note)(协程,同步与异步的性能区别,url爬网页,select,RabbitMq)
1.协程 #协程 又称微线程 是一种用户的轻量级线程 程序级别代码控制 就不用加机器 #不同函数 = 不同任务 A函数切到B函数没有进行cpu级别的切换,而是程序级别的切换就是协程 yelied #单 ...
- Python一路走来 线程 进程
Python线程 Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #!/usr/bin/env pytho ...
- python学习笔记——多进程二 进程的退出
1 进程的退出函数的基础语法 1.1 进程的退出函数 进程的退出含有有os._exit([status])和sys.exit([status])两种,从数据包来看,该退出模块仅在linux或者unix ...
随机推荐
- C#基本工具代码
1.下载Xlsx public static void TryToDisplayGeneratedFileXlsx(string writeFilePath, string fileName) { H ...
- springMVC学习之接受JSON参数
今天在springmvc使用rest模式异步提交,后台接受json字符.发现好多问题,感觉和spring3.0使用习惯上多少有点区别.因此把4.0的异步提交和方式记录下来. 前台页面代码如下: < ...
- tc674div1b
题意:给出n个孩子的初始位置,和每个孩子开始的朝向(左或者右),然后孩子的行走规则是,速度始终为1,两人相遇则两人立即转身背向而行. 现在有q次询问,每次问编号为i的孩子在时间t距离原点的距离.返回所 ...
- MySQL5.6 PERFORMANCE_SCHEMA 说明
背景: MySQL 5.5开始新增一个数据库:PERFORMANCE_SCHEMA,主要用于收集数据库服务器性能参数.并且库里表的存储引擎均为PERFORMANCE_SCHEMA,而用户是不能创建存储 ...
- ABAP BAPI 销售订单生产交货单函数
TYPES: BEGIN OF ty_so, vbeln LIKE vbap-vbeln, posnr LIKE vbap-posnr, END ...
- VC++ 一个简单的Log类
在软件开发中,为程序建立Log日志是很必要的,它可以记录程序运行的状态以及出错信息,方便维护和调试. 下面实现了一个简单的Log类,使用非常简单,仅供参考. // CLogHelper.h : hea ...
- 关于kali2.0 rolling无法连接数据的解决办法
在使用kali2.0时,经常遇到metasploit无法连接数据库的问题,经过在网上寻找资料,很多都是对kali2.0的,有些路径都是不同的了,所以未能解决, 最后在自己的摸索下,找到了如下方法: 其 ...
- 解决xampp端口冲突
今天电脑按了一下xampp,结果运行wamp的时候,出现了下面的情况: 在网上查了一下,结果是端口被占用,然后我就手动修改了一下. 1.修改xampp的端口号 依次找到:XAMPP的安装目录(比如D: ...
- vue-cli构建vue项目
参考资料:Vue2.0 新手完全填坑攻略—从环境搭建到发布 1.Node.js安装 https://nodejs.org/en/download/ 2.安装vue-cli npm install -g ...
- static lib和dynamic lib
lib分为 staticlib 和 dynamic lib: 静态lib将导出声明和实现都放在lib中,编译后所有代码都嵌入到宿主程序, 链接器从静态链接库LIB获取所有被引用函数,并将库同代码一起放 ...