python_线程、进程和协程

线程

Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元。

 1 #!/usr/bin/env python
 2 #coding=utf-8
 3 __author__ = 'yinjia'
 4 
 5 
 6 import threading,time
 7 
 8 def show(arg):
 9     time.sleep(2)
10     print('线程: ' + str(arg))
11 
12 for i in range(5):
13     t = threading.Thread(target=show,args=(i,))
14     t.start()

如上述代码创建了5个线程,target指向函数,arges参数传递数值。

  • 其它方法:
  1. start 线程准备就绪,等待CPU调度
  2. setName 为线程设置名称
  3. getName 获取线程名称
  4. setDaemon 设置为后台线程或前台线程(默认)。如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,均停止;如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止
  5. join 逐个执行每个线程,执行完毕后继续往下执行,该方法使得多线程变得无意义
  6. run 线程被cpu调度后自动执行线程对象的run方法
  • setName\getName使用方法
 1 #!/usr/bin/env python
 2 #coding=utf-8
 3 __author__ = 'yinjia'
 4 
 5 
 6 import threading,time
 7 
 8 def test(i):
 9     print("线程:%s" %str(i))
10     time.sleep(2)
11 
12 for i in range(2):
13     t = threading.Thread(target=test,args=(i,))
14     t.start()
15     t.setName("我的线程: {0}".format(str(i)))
16     print(t.getName())
17 
18 运行结果:
19 线程:0
20 我的线程: 0
21 线程:1
22 我的线程: 1
 1 #!/usr/bin/env python
 2 #coding=utf-8
 3 __author__ = 'yinjia'
 4 
 5 
 6 import threading,time
 7 
 8 class MyThread(threading.Thread):
 9     def __init__(self,num):
10         threading.Thread.__init__(self)
11         self.num = num
12 
13     def run(self):
14         print("running thread:%s" % self.num)
15         time.sleep(2)
16 
17 if __name__ == '__main__':
18     for i in range(2):
19         t1 = MyThread(i)
20         t1.start()
21         t1.setName("我的线程: {0}".format(str(i)))
22         print(t1.getName())
23 
24 运行结果:
25 running thread:0
26 我的线程: 0
27 running thread:1
28 我的线程: 1
自定义线程类
  •  setDaemon方法使用
 1 #!/usr/bin/env python
 2 #coding=utf-8
 3 __author__ = 'yinjia'
 4 
 5 
 6 import threading,time
 7 
 8 def run(num):
 9     print("running thread %s" % str(num))
10     time.sleep(2)
11     print("OK! %s" % str(num))
12 
13 for i in range(2):
14     t = threading.Thread(target=run,args=(i,))
15     #未使用setDaemon时默认是前台线程
16     #t.setDaemon(True)
17     t.start()
18     t.setName("MyThread_{0}".format(str(i)))
19     print(t.getName())
20 
21 运行结果:
22 running thread 0
23 MyThread_0
24 running thread 1
25 MyThread_1
26 OK! 1
27 OK! 0

后台线程:

 1 #!/usr/bin/env python
 2 #coding=utf-8
 3 __author__ = 'yinjia'
 4 
 5 
 6 import threading,time
 7 
 8 def run(num):
 9     print("running thread %s" % str(num))
10     time.sleep(2)
    #主线程执行结束后,不会执行以下语句
11 print("OK! %s" % str(num)) 12 13 for i in range(2): 14 t = threading.Thread(target=run,args=(i,)) 15 #使用setDaemon时是后台线程 16 t.setDaemon(True) 17 t.start() 18 t.setName("MyThread_{0}".format(str(i))) 19 print(t.getName()) 20 21 22 运行结果: 23 running thread 0 24 MyThread_0 25 running thread 1 26 MyThread_1
  •  join用法理解

当未使用join方法时候,先执行完主线程再根据超时决定等待子线程执行完才能程序结束;如果使用join方法,先执行子线程执行完后,才开始执行下一步主线程,此方法没有达到并行效果。

 1 #!/usr/bin/env python
 2 # _*_ coding:utf-8 _*_
 3 __author__ = 'yinjia'
 4 
 5 import time,threading
 6 
 7 def do_thread(num):
 8     time.sleep(3)
 9     print("this is thread %s" % str(num))
10 
11 for i in range(2):
12     t = threading.Thread(target=do_thread, args=(i,))
13     t.start()
14     t.setName("Mythread_{0}".format(str(i)))
15     print("print in main thread: thread name:", t.getName())
16 
17 运行效果:【#先同时执行两个主线程,等待3秒后再执行两个子线程】
18 print in main thread: thread name: Mythread_0  #主线程
19 print in main thread: thread name: Mythread_1  #主线程
20 this is thread 0 #子线程
21 this is thread 1 #子线程

使用join效果如下:

 1 #!/usr/bin/env python
 2 # _*_ coding:utf-8 _*_
 3 __author__ ='yinjia'
 4 
 5 import time,threading
 6 
 7 def do_thread(num):
 8     time.sleep(3)
 9     print("this is thread %s" % str(num))
10 
11 for i in range(2):
12     t = threading.Thread(target=do_thread, args=(i,))
13     t.start()
14     t.join() #增加join
15     t.setName("Mythread_{0}".format(str(i)))
16     print("print in main thread: thread name:", t.getName())
17 
18 
19 运行结果:【先执行子线程,然后再执行主线程,单一逐步执行】
20 this is thread 0
21 print in main thread: thread name: Mythread_0
22 this is thread 1
23 print in main thread: thread name: Mythread_1
  • 线程锁(Lock、RLock)

线程是共享内存,当多个线程对一个公共变量修改数据,会导致线程争抢问题,为了解决此问题,采用线程锁。

 1 #!/usr/bin/env python
 2 # _*_ coding:utf-8 _*_
 3 __author__ = 'Administrator'
 4 
 5 import time,threading
 6 
 7 gl_num = 0
 8 lock = threading.RLock()
 9 
10 def Func():
11     global gl_num
12     #加锁
13     lock.acquire()
14     gl_num += 1
15     time.sleep(1)
16     print(gl_num)
17     #解锁
18     lock.release()
19 
20 for i in range(10):
21     t = threading.Thread(target=Func)
22     t.start()
  • 信号量(Semaphore)

信号量同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。

 1 #!/usr/bin/env python
 2 # _*_ coding:utf-8 _*_
 3 __author__ = 'yinjia'
 4 
 5 import time,threading
 6 
 7 def run(n):
 8     semaphore.acquire()
 9     time.sleep(1)
10     print("run the thread: %s" % n)
11     semaphore.release()
12 
13 if __name__ == '__main__':
14     num = 0
15     semaphore = threading.BoundedSemaphore(5)  # 最多允许5个线程同时运行
16     for i in range(20):
17         t = threading.Thread(target=run, args=(i,))
18         t.start()
  • 事件(event)

事件用于主线程控制其他线程的执行,事件主要提供了三个方法 set、wait、clear。

 1 #!/usr/bin/env python
 2 # _*_ coding:utf-8 _*_
 3 __author__ = 'Administrator'
 4 
 5 import time,threading
 6 
 7 def run(event):
 8     print("start")
 9     event.wait()
10     print('END.....')
11 
12 event_obj = threading.Event()
13 for i in range(2):
14     t = threading.Thread(target=run,args=(event_obj,))
15     t.start()
16 
17 event_obj.clear()
18 inp = input("input: ")
19 if inp == 'true':
20     event_obj.set()
21 
22 #运行结果:
23 start
24 start
25 input: true
26 END.....
27 END.....
  • 条件Condition

满足条件,才能释放N个线程。

 1 #!/usr/bin/env python
 2 # _*_ coding:utf-8 _*_
 3 __author__ = 'Administrator'
 4 
 5 import time,threading
 6 
 7 def condition_func():
 8     ret = False
 9     inp = input('>>>')
10     if inp == '1':
11         ret = True
12     return ret
13 
14 def run(n):
15     con.acquire()
16     con.wait_for(condition_func)
17     print("run the thread: %s" %n)
18     con.release()
19 
20 if __name__ == '__main__':
21 
22     con = threading.Condition()
23     for i in range(10):
24         t = threading.Thread(target=run, args=(i,))
25         t.start()
26 
27 #运行结果:
28 >>>1
29 run the thread: 0
30 >>>1
31 run the thread: 1
32 >>>1
33 run the thread: 2
  • 定时器
 1 #!/usr/bin/env python
 2 # _*_ coding:utf-8 _*_
 3 __author__ = 'Administrator'
 4 
 5 from threading import Timer
 6 
 7 def hello():
 8     print("hello, world")
 9 
10 t = Timer(1, hello)
11 t.start()

 进程

  •  进程数据共享

 方法一:Array

 1 #!/usr/bin/env python
 2 #coding=utf-8
 3 __author__ = 'yinjia'
 4 
 5 
 6 from multiprocessing import Process, Array, RLock
 7 
 8 def Foo(lock,temp,i):
 9     """
10     将第0个数加100
11     """
12     lock.acquire()
13     temp[0] = 100+i
14     for item in temp:
15         print(i,'----->',item)
16     lock.release()
17 
18 lock = RLock()
19 temp = Array('i', [11, 22, 33, 44])
20 
21 for i in range(20):
22     p = Process(target=Foo,args=(lock,temp,i,))
23     p.start()

方法二:manage.dict()共享数据

 1 #!/usr/bin/env python
 2 #coding=utf-8
 3 __author__ = 'yinjia'
 4 
 5 from multiprocessing import Process, Manager
 6 
 7 manage = Manager()
 8 dic = manage.dict()
 9 
10 
11 def Foo(i):
12     dic[i] = 100 + i
13     print(dic)
14     print(dic.values())
15 
16 
17 for i in range(2):
18     p = Process(target=Foo, args=(i,))
19     p.start()
20     p.join()

 

  • 进程池

 进程池方法: 
apply(func[, args[, kwds]]): 阻塞的执行,比如创建一个有3个线程的线程池,当执行时是创建完一个 执行完函数再创建另一个,变成一个线性的执行 
apply_async(func[, args[, kwds[, callback]]]) : 它是非阻塞执行,同时创建3个线程的线程池,同时执行,只要有一个执行完立刻放回池子待下一个执行,并行的执行 
close(): 关闭pool,使其不在接受新的任务。 
terminate() : 结束工作进程,不在处理未完成的任务。 
join() 主进程阻塞,等待子进程的退出, join方法要在close或terminate之后使用。

 1 #!/usr/bin/env python
 2 #coding=utf-8
 3 __author__ = 'yinjia'
 4 
 5 from multiprocessing import Pool
 6 import time
 7 
 8 def myFun(i):
 9     time.sleep(2)
10     return i+100
11 
12 def end_call(arg):
13     print("end_call",arg)
14 
15 p = Pool(5)
16 #print(p.apply(myFun,(1,)))
17 #print(p.apply_async(func =myFun, args=(1,)).get())
18 
19 print(p.map(myFun,range(10)))
20 
21 for i in range(10):
22     p.apply_async(func=myFun,args=(i,),callback=end_call)
23 
24 print("end")
25 p.close()
26 p.join()

 

  • 生产者&消费型

产生数据的模块,就形象地称为生产者;而处理数据的模块,就称为消费者。在生产者与消费者之间在加个缓冲区,我们形象的称之为仓库,生产者负责往仓库了进商 品,而消费者负责从仓库里拿商品,这就构成了生产者消费者模型。

 1 #!/usr/bin/env python
 2 #coding=utf-8
 3 __author__ = 'yinjia'
 4 
 5 
 6 import queue
 7 import threading,time
 8 
 9 
10 message = queue.Queue(10)
11 
12 
13 def producer():
14     name = threading.current_thread().getName()
15     print(name + "线程启动....")
16     for i in range(10):
17         time.sleep(1)
18         print('\033[45m<%s> 生产了 [%s]个饺子\033[0m' % (name, i))
19         message.put(name)
20 
21 
22 def consumer():
23     name = threading.current_thread().getName()
24     print(name + "线程启动.....")
25     for i in range(10):
26         message.get()
27         print('\033[43m<%s> 吃了 [%s]个饺子\033[0m' % (name, i))
28 
29 
30 if __name__ == '__main__':
31 
32     p = threading.Thread(target=producer, name='东北饺子店')
33     c = threading.Thread(target=consumer, name='消费者')
34     p.start()
35     c.start()

 运行结果:

 

协程

协程存在的意义:对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时(保存状态,下次继续)。协程,则只使用一个线程,在一个线程中规定某个代码块执行顺序。

协程的适用场景:当程序中存在大量不需要CPU的操作时(IO),适用于协程;

  • gevent
 1 #!/usr/bin/env python
 2 # _*_ coding:utf-8 _*_
 3 __author__ = 'Administrator'
 4 
 5 import gevent
 6 
 7 def foo():
 8     print('Running in foo')
 9     gevent.sleep(0)
10     print('Explicit context switch to foo again')
11 
12 def bar():
13     print('Explicit context to bar')
14     gevent.sleep(0)
15     print('Implicit context switch back to bar')
16 
17 gevent.joinall([
18     gevent.spawn(foo),
19     gevent.spawn(bar),
20 ])
21 
22 #运行结果:
23 Running in foo
24 Explicit context to bar
25 Explicit context switch to foo again
26 Implicit context switch back to bar
  • 遇到IO操作自动切换
 1 #!/usr/bin/env python
 2 # _*_ coding:utf-8 _*_
 3 
 4 from gevent import monkey; monkey.patch_all()
 5 import gevent
 6 import urllib.request
 7 
 8 def f(url):
 9     print('GET: %s' % url)
10     resp = urllib.request.urlopen(url)
11     data = resp.read()
12     print('%d bytes received from %s.' % (len(data), url))
13 
14 gevent.joinall([
15         gevent.spawn(f, 'https://www.python.org/'),
16         gevent.spawn(f, 'https://www.baidu.com/'),
17         gevent.spawn(f, 'https://github.com/'),
18 ])
19 
20 #运行结果:
21 GET: https://www.python.org/
22 GET: https://www.baidu.com/
23 GET: https://github.com/
24 227 bytes received from https://www.baidu.com/.
25 49273 bytes received from https://www.python.org/.
26 53756 bytes received from https://github.com/.

 上下文管理

 1 #!/usr/bin/env python
 2 # _*_ coding:utf-8 _*_
 3 __author__ = 'Administrator'
 4 
 5 import contextlib
 6 
 7 @contextlib.contextmanager
 8 def tag(name):
 9     print("<%s>" % name)
10     yield
11     print("</%s>" % name)
12 
13 with tag("h1"):
14     print("foo")
15 
16 #运行结果:
17 <h1>
18 foo
19 </h1>
 1 #!/usr/bin/env python
 2 # _*_ coding:utf-8 _*_
 3 __author__ = 'Administrator'
 4 
 5 import contextlib
 6 
 7 @contextlib.contextmanager
 8 def myopen(file_path,mode):
 9     f = open(file_path,mode,encoding='utf-8')
10     try:
11         yield f
12     finally:
13         f.close()
14 with myopen('index.html','r') as file_obj:
15     for i in file_obj:
16         print(i)

更多方法参见:https://docs.python.org/3.6/library/contextlib.html

转载于:https://www.cnblogs.com/yinjia/p/8683146.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/251898.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第四章:手机平板要兼顾-探究碎片

碎片是什么&#xff1f; 碎片&#xff08;Fragment&#xff09;是一种可以嵌入在活动&#xff08;Activity&#xff09;中的 UI 片段&#xff0c;它能让程序更加合理和充分的利用大屏幕的空间&#xff0c;因而在平板上应用的非常广泛。 碎片的使用方式 静态嵌入动态加载碎片和活…

Android Studio 3.4增可视化资源管理工具 可管理和预览项目资源

经过6个月的开发时间&#xff0c;网络大厂17日发布了最新版的App开发IDE Android Studio 3.4&#xff0c;现在就能够下载使用&#xff0c;除了有超过300个错误修护和稳定度增强之外&#xff0c;在开发、建置和测试App阶段&#xff0c;都推出了一些小的新功能和工具&#xff0c;…

[IoC容器Unity]第三回:依赖注入

上节介绍了&#xff0c;Unity的Lifetime Managers生命周期&#xff0c;Unity具体实现依赖注入包含构造函数注入、属性注入、方法注入&#xff0c;所谓注入相当赋值&#xff0c;下面一个一个来介绍。 2.构造函数注入 Unity利用Resolve方法解析一个对象&#xff0c;都是调用注册类…

Apache CarbonData 1.5.0编译及安装

2019独角兽企业重金招聘Python工程师标准>>> 一、编译环境描述 OpenStack创建五个虚拟机&#xff0c;其中1个主节点&#xff08;hostname为bigdatamaster&#xff09;&#xff0c;4个从节点&#xff08;hostname分别为&#xff0c;bigdataslave1、bigdataslave2、bi…

Filter介绍

Filter 可认为是 Servlet的一种 “ 加强版 ”&#xff0c;它主要用于对用户请求进行预处理&#xff0c; 也可以对HttpServletResponse 进行后处理&#xff0c;是个典型的处理链。Filter 也可对用户请求生成响应&#xff0c;这一 点与Servlet 相同&#xff0c; 但实际上很少会使…

python --- 二分查找算法

二分查找法&#xff1a;在我的理解中这个查找方法为什么会叫二分呢&#xff0c;我认为是将要查询的一个列表分成了两份&#xff0c;然后在利用某个值来进行比较&#xff0c;在一个不断循环的过程中来找出我们要找的某一个值。 废话不多说&#xff0c;先上代码&#xff1a; 1 de…

Java暑假作业

一.《大护法》观影有感 ... 从预告开始就期待着这部影片&#xff0c;在看过一遍后又忍不住二刷&#xff0c;影片观看至第二遍后&#xff0c;对于全片的脉络也更清晰了一点&#xff0c;虽然打着暴力美学的旗子&#xff0c;但《大护法》偏偏更文艺一些。文艺片是没有对错的&a…

使用EasyNetQ组件操作RabbitMQ消息队列服务

RabbitMQ是一个由erlang开发的AMQP(Advanved Message Queue)的开源实现&#xff0c;是实现消息队列应用的一个中间件&#xff0c;消息队列中间件是分布式系统中重要的组件&#xff0c;主要解决应用耦合&#xff0c;异步消息&#xff0c;流量削锋等问题。实现高性能&#xff0c;…

TensorFlow 1.12.2 发布,修复 GIF 构造安全漏洞

开发四年只会写业务代码&#xff0c;分布式高并发都不会还做程序员&#xff1f; TensorFlow 1.12.2 发布了&#xff0c;此处本修复了一个潜在的安全漏洞&#xff1a; 精心设计的 GIF 图像可以在解码过程中产生空指针解引用更新说明&#xff1a; https://github.com/tensorflo…

对象变为指定格式的数组

拿到的对象的格式&#xff08;一个对象里面都好多属性&#xff09; 想要转换成的数据格式&#xff08;一个数组里面有好多个对象&#xff0c;每个对象有一个id和name的属性&#xff09; 如何处理的 selectionChange(val) { // 列表选择var dynamicTags1 [];var arr[]for(var i…

mysql学习(2)索引的本质

2019独角兽企业重金招聘Python工程师标准>>> 问题&#xff1a;SQL查询慢怎么办&#xff1f; 优化手段&#xff0c;加索引。 索引是帮助MYSQL高效的获取数据的排好序的数据结构。 问题&#xff1a;索引结构为什么使用Btree而不使用二叉树&#xff0c;红黑树或者HASH结…

CSS3:CSS3 文本效果

ylbtech-CSS3&#xff1a;CSS3 文本效果1.返回顶部 1、CSS3 文本效果 CSS3 文本效果 CSS3中包含几个新的文本特征。 在本章中您将了解以下文本属性&#xff1a; text-shadowbox-shadowtext-overflowword-wrapword-break浏览器支持 属性 text-shadow4.010.03.54.09.5box-sha…

洛谷 P2296 寻找道路

题目描述 在有向图G 中&#xff0c;每条边的长度均为1 &#xff0c;现给定起点和终点&#xff0c;请你在图中找一条从起点到终点的路径&#xff0c;该路径满足以下条件&#xff1a; 1 &#xff0e;路径上的所有点的出边所指向的点都直接或间接与终点连通。 2 &#xff0e;在满足…

Feature Preprocessing on Kaggle

刚入手data science, 想着自己玩一玩kaggle&#xff0c;玩了新手Titanic和House Price的 项目, 觉得基本的baseline还是可以写出来&#xff0c;但是具体到一些细节&#xff0c;以至于到能拿到的出手的成绩还是需要理论分析的。 本文旨在介绍kaggle比赛到各种原理与技巧&#xf…

如果您遇到文件或数据库问题,如何重置Joomla

2019独角兽企业重金招聘Python工程师标准>>> 如果您遇到Joomla站点的问题&#xff0c;那么重新安装其核心文件和数据库可能是最佳解决方案。 了解问题 这种方法无法解决您的所有问题。但它主要适用于由Joomla核心引起的问题。 运行Joomla核心更新后&#xff0c;这些…

Genymotion模拟器拖入文件报An error occured while deploying the file的错误

今天需要用到资源文件&#xff0c;需要将资源文件拖拽到sd卡中&#xff0c;但老是出现这个问题&#xff1a; 资源文件拖不进去genymotion。查看了sd的DownLoad目录&#xff0c;确实没有成功拖拽进去。 遇到这种问题的&#xff0c;我按下面的思路排查问题&#xff1a; Genymotio…

激光炸弹(BZOJ1218)

激光炸弹&#xff08;BZOJ1218&#xff09; 一种新型的激光炸弹&#xff0c;可以摧毁一个边长为R的正方形内的所有的目标。现在地图上有n(N<10000)个目标&#xff0c;用整数Xi,Yi(其值在[0,5000])表示目标在地图上的位置&#xff0c;每个目标都有一个价值。激光炸弹的投放是…

用servlet设计OA管理系统时遇到问题

如果不加单引号会使得除变量和int类型的值不能传递 转发和重定向的区别 转发需要填写完整路径&#xff0c;重定向只需要写相对路径。原因是重定向是一次请求之内已经定位到了服务器端&#xff0c;转发则需要两次请求每次都需要完整的路径。 Request和response在解决中文乱码时的…

[Usaco2010 Mar]gather 奶牛大集会

1827: [Usaco2010 Mar]gather 奶牛大集会 Time Limit: 1 Sec Memory Limit: 64 MB Submit: 1129 Solved: 525 [Submit][Status][Discuss]Description Bessie正在计划一年一度的奶牛大集会&#xff0c;来自全国各地的奶牛将来参加这一次集会。当然&#xff0c;她会选择最方便的…

1-1、作用域深入和面向对象

课时1&#xff1a;预解释 JS中的数据类型 number、string、 boolean、null、undefined JS中引用数据类型 object: {}、[]、/^$/、Date Function var num12; var obj{name:白鸟齐鸣,age:10}; function fn(){ console.log(勿忘初心方得始终&#xff01;) }console.log(fn);//把整…