一、进程与线程简介

  • 进程

进程是程序的一次执行,由进程段、数据段、进程控制块三部分组成。具体三个基本状态,就绪、执行、阻塞,是一个拥有资源的独立单位。

  • 线程

属于进程的一个实体,拥有极少的资源。也具有三个基本状态,就绪、执行、拥塞。可以认为是一个情形进程。

  • 关系

一个进程可以创建多个线程;一个进程创建的多个线程共享其资源;

进程开销较大,线程开销较小;进程撤销时间长,线程撤销时间短。

  • 多进程/线程的运行

由主机的操作系统给每个进程/线程安排一个小时间片,在所有的进程/线程中快速切换,使每个执行单元都能得到CPU的执行时间。

多核系统上多进程分用不同的CPU核心。

  • 注意点

python解释器内部使用了全局解释器锁(GIL),现在python进程只能在一个CPU核上运行。

二、进程的生命周期

三、python中threading模块

  • Thread对象:用来创建线程
  • Thread对象属性:
  1. start():启动线程
  2. run():启动线程的方法
  3. join():等待
  4. is_alive():返回该线程的活动状态
  5. name:线程名
  6. id:线程ID
  7. deamon:后台标志
  • 获取当前线程

  current_thread()

  • 获取所有活动线程

  enumerate()

四、线程的创建方法

1、直接实例化threading中Thread对象,并将线程的参数传入

  实例化参数如下:

  Thread(target = None,name = None,args = (),kwargs = {})

  1. target参数为要传入的函数名
  2. name参数为线程的名称
  3. args元组行参数
  1. import threading
  2. import time
  3.  
  4. def calc():
  5. sum = 0
  6. for i in range(30):
  7. sum += i
  8. time.sleep(0.1)
  9. print(sum)
  10.  
  11. if __name__ == '__main__':
  12. ths = [threading.Thread(target = calc) for i in range(2)]
  13. for th in ths:
  14. th.start()

运行结果:

  1. 435
  2. 435

2、通过继承Threading中的Thread对象,然后实例化并启动它。

注:新定义的Thread中如果定义了__init__(),需要先调用父类的__init__()

  1. import threading
  2. import time
  3.  
  4. class MyThread(threading.Thread):
  5. def run(self):
  6. sum = 0
  7. for i in range(30):
  8. sum += i
  9. time.sleep(0.1)
  10. print(sum)
  11.  
  12. if __name__ == '__main__':
  13. ths = [MyThread() for i in range(2)]
  14. for th in ths:
  15. th.start()

  

五、线程之间的关系

  • 独立线程

  • 等待线程

  • 后台线程

  • 线程同步1

共享资源只能被一个线程使用,先到先得

  • 线程同步2

操作有先后,典型的例子是生产者与消费者。线程A先操作,做一些初始化动作,线程B才能使用。

  • 线程同步3

资源个数有上限

  • 线程通信

六、线程各关系的实现

1、等待线程

join方法,被调用join方法的线程一直拥塞调用者的线程,直到自己结束。

也就是一个线程等待另一线程运行完才开始运行

  1. import threading,time
  2.  
  3. class MyThread(threading.Thread):
  4. def run(self):
  5. for i in range(9):
  6. print('thread:',i)
  7. time.sleep(0.1)
  8.  
  9. if __name__ == '__main__':
  10. m = MyThread()
  11. m.start()
  12. m.join()
  13. for i in range(5):
  14. print('main:',i)
  15. time.sleep(0.1)

运行结果:

  1. thread: 0
  2. thread: 1
  3. thread: 2
  4. thread: 3
  5. thread: 4
  6. thread: 5
  7. thread: 6
  8. thread: 7
  9. main: 0
  10. main: 1
  11. main: 2
  12. main: 3
  13. main: 4

2、后台线程

被设置为后台运行的线程,会在主程序退出时自杀

实现步骤:

  1. 建立线程
  2. 设置线程的deamon属性为True
  3. 启动线程
  1. import threading,time
  2.  
  3. def backthread():
  4. print('backthread start...')
  5. time.sleep(3)
  6. print('backthread end...')
  7.  
  8. def mainthread():
  9. print('mainthread start...')
  10. time.sleep(1)
  11. print('mainthread end...')
  12.  
  13. th1 = threading.Thread(target = backthread)
  14. th1.deamon = True
  15.  
  16. th2 = threading.Thread(target = mainthread)
  17. print('start...')
  18. th1.start()
  19. th2.start()
  20. print('end...')

运行结果:

  1. start...
  2. backthread start...
  3. mainthread start...
  4. end...
  5. mainthread end...
  6. backthread end...

2、线程同步    

2.1 指令锁threading.Lock

  • 加锁 acquire(blocking = True,timeout = -1)
  • 释放锁 release()
  1. import threading,time,random
  2.  
  3. share = 4
  4. class MyThread(threading.Thread):
  5. def __init__(self,i):
  6. super().__init__()
  7. self.i = i
  8.  
  9. def run(self):
  10. global share
  11. for i in range(3):
  12. lock.acquire()
  13. print(share)
  14. share += self.i
  15. time.sleep(random.random())
  16. print('+',self.i,'=',share)
  17. lock.release()
  18.  
  19. lock = threading.Lock()
  20.  
  21. if __name__ == '__main__':
  22. m = MyThread(2)
  23. mm = MyThread(6)
  24. m.start()
  25. mm.start()

运行结果:

  1. 4
  2. + 2 = 6
  3. 6
  4. + 2 = 8
  5. 8
  6. + 6 = 14
  7. 14
  8. + 6 = 20
  9. 20
  10. + 6 = 26
  11. 26
  12. + 2 = 28

2.2 可重入锁 threading.RLock

与指令锁的区别,对于已经锁定的资源,在该线程内部还可以在锁一次。

支持的方法:

  • acquire(block = Ture,timeout = -1)
  • release()  

锁定多少次,就要释放多少次!

2.3 条件变量threading.Condition

支持的方法:

  • acquire()
  • release()
  • wait(timeout = None) 释放锁进入等待拥塞,直到唤醒或者超时,这个线程才会继续运行。
  • notify(n = 1) 如果一个线程处于wait状态,使用notify()进行唤醒
  • notify_all 唤醒所有线程

使用范围:

  实现严格次序操作的线程间通信

典型实例:

  生产者/消费者(先生产,后消费)

线程之间可以相互通知,已达到默契的配合

  1. import threading,time
  2.  
  3. share = 0
  4. share_cond = threading.Condition()
  5.  
  6. class ProThread(threading.Thread):
  7. def __init__(self):
  8. super().__init__()
  9. self.name = 'produce'
  10.  
  11. def run(self):
  12. global share
  13. if share_cond.acquire():
  14. while True:
  15. if not share:
  16. share += 1
  17. print(self.name,share)
  18. share_cond.notify()
  19. share_cond.wait()
  20. time.sleep(1)
  21.  
  22. class CustomTread(threading.Thread):
  23. def __init__(self):
  24. super().__init__()
  25. self.name = 'produce'
  26.  
  27. def run(self):
  28. global share
  29. if share_cond.acquire():
  30. while True:
  31. if share:
  32. share -= 1
  33. print(self.name,share)
  34. share_cond.notify()
  35. share_cond.wait()
  36. time.sleep(1)
  37.  
  38. if __name__ == '__main__':
  39. p = ProThread()
  40. c = CustomTread()
  41. p.start()
  42. c.start()

运行结果:

  1. produce 1
  2. produce 0
  3. #一直循环下去...

2.4 信号量 threading.Semaphore()

实例化是指定使用量

支持的方法:

  • acquire(blocking = Ture,timeout = None) 锁定资源
  • release() 释放锁

  使用其内置计数器,锁定时+1;释放时-1;计数器为0则拥塞

使用范围:

  用于实现对稀缺资源的控制,比如需要控制稀缺资源的用户数

  1. import threading,time
  2.  
  3. sema = threading.Semaphore(2)
  4.  
  5. class SemaThread(threading.Thread):
  6. def __init__(self,name):
  7. super().__init__()
  8. self.name = name
  9.  
  10. def run(self):
  11. if sema.acquire():
  12. print(self.name,' get resource.')
  13. time.sleep(1)
  14. print(self.name,' release resource.')
  15. sema.release()
  16.  
  17. if __name__ == '__main__':
  18. res = [SemaThread(str(i) + 'sema') for i in range(5)]
  19. for i in res:
  20. i.start()

运行结果:

  1. 0sema get resource.
  2. 1sema get resource.
  3. 1sema release resource.
  4. 0sema release resource.
  5. 3sema get resource.
  6. 2sema get resource.
  7. 2sema release resource.
  8. 3sema release resource.
  9. 4sema get resource.
  10. 4sema release resource.

3、线程通信 threading.Event()

作用:

  管理一个内部标志,实现一个线程,唤醒其他线程

支持的方法:

  • set() 设置内部标志位False
  • clear() 设置内部标志为False
  • wait([timeout])拥塞线程,直到内部标志位True
  1. import threading,time
  2.  
  3. eve = threading.Event()
  4.  
  5. class MyThreadWait(threading.Thread):
  6. def run(self):
  7. self.name = 'Wait Thread'
  8. print(self.name,'waitting...')
  9. eve.wait()
  10. print(self.name,'Start...')
  11. eve.clear()
  12.  
  13. class MyThreadMain(threading.Thread):
  14. def run(self):
  15. time.sleep(3)
  16. print('Main thread set event flag!')
  17. eve.set()
  18.  
  19. if __name__ == '__main__':
  20. mm = MyThreadMain()
  21. mw = MyThreadWait()
  22. mm.start()
  23. mw.start()

运行结果:

  1. Wait Thread waitting...
  2. Main thread set event flag!
  3. Wait Thread Start...

4、定时执行threading.Timer

使用方法:

  threading.Timer(3,start)

说明:

  此进程3sec之后运行

  

python之线程学习的更多相关文章

  1. python自动化开发学习 进程, 线程, 协程

    python自动化开发学习 进程, 线程, 协程   前言 在过去单核CPU也可以执行多任务,操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换任务2,任务2执行0.01秒,在切换到任务3,这 ...

  2. Python之线程、进程和协程

    python之线程.进程和协程 目录: 引言 一.线程 1.1 普通的多线程 1.2 自定义线程类 1.3 线程锁 1.3.1 未使用锁 1.3.2 普通锁Lock和RLock 1.3.3 信号量(S ...

  3. python threading基础学习

    # -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' """ python是支持多线程的,并 ...

  4. python全栈学习--day1

      计算机基础 CPU:中央处理器 内存:4GB,8GB,临时处理事务的地方,供给CPU数据. 硬盘:相当于电脑的数据库,存储着大量的数据,文件,电影等. 操作系统:执行者,支配所有关系 window ...

  5. 一文了解Python的线程

    问题 什么是线程? 如何创建.执行线程? 如何使用线程池ThreadPoolExecutor? 如何避免资源竞争问题? 如何使用Python中线程模块threading提供的常用工具? 目录 1. 什 ...

  6. 《Python》线程池、携程

    一.线程池(concurrent.futures模块) #1 介绍 concurrent.futures模块提供了高度封装的异步调用接口 ThreadPoolExecutor:线程池,提供异步调用 P ...

  7. python源码学习(一)——python的总体架构

    python源码学习(一)——python的总体架构 学习环境: 系统:ubuntu 12.04 STLpython版本:2.7既然要学习python的源码,首先我们要在电脑上安装python并且下载 ...

  8. 孤荷凌寒自学python第四十三天python 的线程同步之Queue对象

     孤荷凌寒自学python第四十三天python的线程同步之Queue对象 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) Queue对象是直接操作队列池的对象,队列中可以存放多种对象,当然也 ...

  9. 孤荷凌寒自学python第四十一天python的线程同步之Event对象

     孤荷凌寒自学python第四十一天python的线程同步之Event对象 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 鉴于Lock锁与RLock锁均宣告没有完全完成同步文件操作的问题,于 ...

随机推荐

  1. [js高手之路]深入浅出webpack教程系列8-(postcss-loader,autoprefixer,html-loader,less-loader,ejs-loader)用法

    我们接着上文,那么在上篇文章的最后,写到了css-loader的用法,如果你用心发现,就能看到我在style.css样式文件中写了一个这样的样式: div { transition: all ease ...

  2. [转]Java中的随机数生成器:Random,ThreadLocalRandom,SecureRandom

     详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp84 Random即:java.util.Random, ThreadL ...

  3. 转:【Java并发编程】之十:使用wait/notify/notifyAll实现线程间通信的几点重要说明

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17225469    在Java中,可以通过配合调用Object对象的wait()方法和no ...

  4. Beta阶段事后诸葛亮分析

    1.总结的提纲内容 a. 项目管理之事后诸葛亮会 设想和目标 1.我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们的软件主要解决用户无意识花钱,无法清楚看见钱去 ...

  5. Java单元测试之覆盖率统计eclemma

    安装 有两种安装方法 下载安装(推荐) 地址: http://sourceforge.net/projects/eclemma/ 将解压后的features和plugins目录下的文件分别拷贝到Ecl ...

  6. 团队作业8——第二次项目冲刺(Beta阶段)--第七天

    会议照片: 燃尽图: 项目进展: 所有项目都已完成 进行app测试即使用情况评估 团队贡献比: 队员 角色 团队贡献比 陈麟凤 PM 17% 张志杰 DEV 18% 黄海鸿 TEST 16% 康建灿 ...

  7. 201521123022 《Java程序设计》 第五周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 2. 书面作业 1.代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过? ...

  8. 201521123003《Java程序设计》第4周学习总结

    1. 本章学习总结 你对于本章知识的学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 参考资料: 百度脑图 XMind 1.2 使用常规方法总结其他上课内容. (1)了解了类型转换(cast) ...

  9. 201521123087 《Java程序设计》第3周学习总结

    1.本周学习总结 2. 书面作业 代码阅读 public class Test1 { private int i = 1;//这行不能修改 private static int j = 2; publ ...

  10. Java中的基本数据类型和基本数据类型之间的转换

    在Java中有8中基本数据类型,分别为: 整型: byte.short.int.long 浮点型:float.double 布尔型:boolean 字符型:char. byte:    8位,  封装 ...