线程

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

python_线程、进程和协程相关推荐

  1. 线程 、进程、协程 三者区别

    从计算机硬件角度: 计算机的核心是CPU,承担了所有的计算任务. 一个CPU,在一个时间切片里只能运行一个程序. 从操作系统的角度: 进程和线程,都是一种CPU的执行单元. 进程:表示一个程序的上下文 ...

  2. Python中的线程、进程、协程以及区别

    进程,是执行中的计算机程序.也就是说,每个代码在执行的时候,首先本身即是一个进程.一个进程具有:就绪,运行,中断,僵死,结束等状态(不同操作系统不一样). 运行中每个进程都拥有自己的地址空间.内存.数 ...

  3. Python 线程和进程和协程总结

    Python 线程和进程和协程总结 线程和进程和协程 进程 进程是程序执行时的一个实例,是担当分配系统资源(CPU时间.内存等)的基本单位: 进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其 ...

  4. Python之路,Day9 - 线程、进程、协程和IO多路复用

    参考博客: 线程.进程.协程: http://www.cnblogs.com/wupeiqi/articles/5040827.html http://www.cnblogs.com/alex3714 ...

  5. Python 37 进程池与线程池 、 协程

    一:进程池与线程池 提交任务的两种方式: 1.同步调用:提交完一个任务之后,就在原地等待,等任务完完整整地运行完毕拿到结果后,再执行下一行代码,会导致任务是串行执行 2.异步调用:提交完一个任务之后, ...

  6. linux的进程/线程/协程系列1:进程到协程的演化

    linux的进程/线程/协程系列1:进程到协程的演化 前言 摘要: 1. 一些历史:批处理时代 2. 现代操作系统启动过程 3. 进程(process)的出现 4. 线程(thread)与线程池 5. ...

  7. 教你打开线程、进程和协程的大门!

    作者 | 蓝  责编 | 张文 头图 | CSDN 下载自视觉中国 不知从几何起,可能是大三那年的操作系统考试,也可能是刚经历完的秋招,这些概念总是迷迷糊糊,可能自己回答的和其他人的答复也差不多,并没 ...

  8. Python_oldboy_自动化运维之路_线程,进程,协程(十一)

    本节内容: 线程 进程 协程 IO多路复用 自定义异步非阻塞的框架 线程和进程的介绍: 举个例子,拿甄嬛传举列线程和进程的关系: 总结: 1.工作最小单元是线程,进程说白了就是提供资源的 2.一个应用 ...

  9. 关于进程线程和Go协程总结

    导语 我们都知道Golang的最大特性就是Goroutine(协程)的设计,那究竟什么是协程呢?它和计算机中的进程和线程又有哪些区别呢?为什么协程可以同时并发,几乎不占内存,想必在你的心中有了类似这样 ...

  10. 一个小故事讲明白进程、线程、Kotlin 协程到底啥关系?

    前言 协程系列文章: 一个小故事讲明白进程.线程.Kotlin 协程到底啥关系? 少年,你可知 Kotlin 协程最初的样子? 讲真,Kotlin 协程的挂起/恢复没那么神秘(故事篇) 讲真,Kotl ...

最新文章

  1. python代码基础题-Python基础练习题
  2. 【Python基础】这份 pip 使用小抄,要有全有多全(建议收藏)
  3. 如何找到cache-control header是从后台何处设置的
  4. 5177. 【NOIP2017提高组模拟6.28】TRAVEL (Standard IO)
  5. 数学-矩阵计算(1)矩阵和向量的求导法则
  6. Java多线程(十):BlockingQueue实现生产者消费者模型
  7. 索引法则--尽量使用覆盖索引
  8. oracle手把手教学资料
  9. 思科最模拟器Cisco Packet Tracer 7.3.0安装配置
  10. windows系统下Studio3T下载与安装
  11. what is a rx ring/tx ring in router?
  12. 恒流源差分放大电路静态分析_带有恒流源的差动放大电路
  13. 推荐10 款 C++ 在线编译器
  14. eclipse安装sdk和adt
  15. WordPress主题CorePress
  16. 强哥语录摘抄(郑强教授)
  17. IOS学习之路二十四(custom 漂亮的UIColor)
  18. 泊车机器人整车控制策略
  19. matlab 控制图例个数,MATLAB 识别图像中米粒个数
  20. 魔方机器人(基于OpenCV、Arduino)

热门文章

  1. Detectron2学习笔记
  2. 方差、标准差、均方根误差
  3. 深度学习与计算机视觉(四)反向传播及其直观理解
  4. 老赖整治升级,不还钱直接扣微信钱包!
  5. 《中国当代乡土小说大系》明年出版
  6. HDMI显示器驱动设计与验证
  7. 嵌入式linux通过DHCP自动获取IP地址实现
  8. 身体好不是锻炼出来的
  9. python读取html_从零开始的Python爬虫教程(一):获取HTML文档
  10. jedis使用_Redis --Java客户端 Jedis