热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Python学习之路(五)————线程、进程

Python学习之路(五)————线程、进程以下所用的是Python3.6。使用PyCharmIDE。一、概念及区别1.1概念进程是具有一定独立功能的程

Python 学习之路(五)————线程、进程

以下所用的是Python 3.6。使用PyCharm IDE。

一、概念及区别

1.1 概念

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。譬如说QQ、360安全卫士这些程序都是一个进程。简单来说就是资源的集合。

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。 一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行。譬如说360安全卫士可以同时查杀病毒,清理缓存,这就是一个进程中启用了多个线程。简单来说就是资源调度的基本单位。

1.2 关系与区别

进程和线程的关系:

  • 一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
  • 资源分配给进程,同一进程的所有线程共享该进程的所有资源。
  • 处理机分给线程,即真正在处理机上运行的是线程。
  • 线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。线程是指进程内的一个执行单元,也是进程内的可调度实体.

进程与线程的区别:

  • 调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
  • 并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行
  • 拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源,有一个共享的程序资源空间
  • 系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销

二、线程部分

2.1 调用的两种方式

直接调用

import threading
import timedef run(args):print("%s runing"% args)time.sleep(3)t1 = threading.Thread(target=run,args=("task one",))
t2
= threading.Thread(target=run,args=("task two",))
t1.start()
t2.start()

直接调用

继承调用

import threading
import timeclass MyThread(threading.Thread): #继承Thread类def __init__(self,msg):threading.Thread.__init__(self)self.msg = msgdef run(self):print("%s is running" % self.msg)time.sleep(3)if __name__ == "__main__":t1 = MyThread("task one")t2 = MyThread("task two")t1.start()t2.start()

继承调用

2.2 线程模块

threading 模块提供的其他方法

  • threading.currentThread(): 返回当前的线程变量。
  • threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
  • threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

Thread类提供了以下方法

  • run(): 用以表示线程活动的方法。
  • start():启动线程活动。
  • join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
  • isAlive(): 返回线程是否活动的。
  • getName(): 返回线程名。
  • setName(): 设置线程名。

threading 可用对象列表

  • Thread 表示执行线程的对象
  • Lock 锁原语对象
  • RLock 可重入锁对象,使单一进程再次获得已持有的锁(递归锁)
  • Condition 条件变量对象,使得一个线程等待另一个线程满足特定条件,比如改变状态或某个值
  • Semaphore 为线程间共享的有限资源提供一个”计数器”,如果没有可用资源会被阻塞
  • Event 条件变量的通用版本,任意数量的线程等待某个时间的发生,在改事件发生后所有线程被激活
  • Timer 与 Thread 相识,不过它要在运行前等待一段时间
  • Barrier 创建一个”阻碍”,必须达到指定数量的线程后才可以继续

2.3 互斥锁 Mutex

互斥锁,防止多个线程使用同一份资源(数据)产生错误,保证线程同步。 如下例所示,如果没有lock这个锁,可能会导致num结果出错。注:请在2.X上调试,3.0以上可能自动加了锁,没有出现问题。

import threading, timenum = 0def run(args): #线程运行函数lock.acquire() #上锁global num #获取全局变量time.sleep(0.1)num += 1print("%s runing"% args)lock.release() #开锁

lock
= threading.Lock() #定义互斥锁

thread_list
= [] #定义线程列表for i in range(50): #创建50个线程t = threading.Thread(target=run,args=(i,))t.start()thread_list.append(t)for thread in thread_list: #等待全部线程结束
thread.join()print(num)

互斥锁案例

2.4 递归锁(重入锁) RLock

重入锁必须由获取它的线程释放。 一旦线程获得了一个可重入的锁,同一个线程可能会再次获取它没有阻塞; 该线程每次都必须释放一次获得它。

import threadingdef run(): #线程调用函数 对num计数print("threading %s" % threading.get_ident())lock.acquire()global numnum += 1lock.release()return numdef run2():#线程运行函数,完成调用两次run函数
lock.acquire()res1= run()res2 = run()lock.release()print("res1:%s res2:%s"%(res1, res2))if __name__ == '__main__':num = 0lock = threading.RLock() #定义重入锁,不加重入锁程序会导致死锁for i in range(10): #开启10个线程t = threading.Thread(target=run2)t.start()while threading.active_count() > 1: #活动线程数小于等于1时,退出循环passelse:print(num)

重入锁案例

2.5 信号量 Semaphore

Semaphore是同时允许一定数量的线程更改数据,有界信号量检查以确保其当前值不超过其初始值。 案例:做多只能有5个线程同时作业

import threading, timedef work(n): #作业线程运行函数semaphore.acquire() #获取信号量,会在当前信号量总数count的基础上加1time.sleep(1)print("this is %s work" % n)semaphore.release() #释放信号量,中当前信号量的总数上减1if __name__ == '__main__':semaphore = threading.BoundedSemaphore(5) #信号量最大总数为5,当到达5时,# 其他线程需要继续获取信号量,会等待其他线程释放for i in range(1,100):t = threading.Thread(target=work, args=(i,))t.start()while threading.active_count() != 1:passelse:print('----all works done---')

信号量案例

2.6 简单的生产者,消费者案例

生产者,消费者案例是在多线程同步问题中的典型案例

import threading,time,queuedef producer(name,q): #生产者线程运行函数for i in range(100):if q.qsize() <&#61; 5:lock.acquire() # 对缓存区操作时&#xff0c;需要上锁q.put("产品%s" % i)print("%s 生产 产品%i"%(name,i))lock.release() #操作完毕解锁time.sleep(0.1)else:time.sleep(0.1)def consumer(name,q): #消费者线程运行函数while True:if q.qsize() > 0:lock.acquire()#对缓存区操作时&#xff0c;需要上锁print("%s 消费 %s"%(name,q.get()))lock.release() #操作完毕解锁time.sleep(0.2)if __name__ &#61;&#61; "__main__":q &#61; queue.Queue() #定义资源缓存区lock &#61; threading.Lock() #定义资源互斥锁pro1 &#61; threading.Thread(target&#61;producer,args&#61;("生产者1",q,))pro2 &#61; threading.Thread(target&#61;producer,args&#61;("生产者2",q,))con1 &#61; threading.Thread(target&#61;consumer,args&#61;("消费者1",q,))con2 &#61; threading.Thread(target&#61;consumer,args&#61;("消费者2",q,))pro1.start()pro2.start()con1.start()con2.start()

生产者消费者案例

三、进程部分

3.1 进程的简单调用

from multiprocessing import Process
import time,osdef fun(name):time.sleep(2)print("this is new process&#xff1a;", name)print("parent process:", os.getppid()) #获取父进程idprint("process id:", os.getpid()) #获取当前进程idif __name__ &#61;&#61; "__main__":print("current process:",os.getpid()) #获取当前进程idp &#61; Process(target&#61;fun, args&#61;("test",))p.start()p.join()

进程调用

3.2 进程间通信

可以通过Queue、Pipes等多种方式来交换数据

Queue通信案例

from multiprocessing import Process, Queue
import timedef send(q): #发送进程函数msgs &#61; ["Hello","python","process"]for msg in msgs:q.put(msg)time.sleep(1)def recv(q): #接收进程函数while True:print("recv msg : %s from another process" % q.get(True))if __name__ &#61;&#61; &#39;__main__&#39;:q &#61; Queue()send_process &#61; Process(target&#61;send, args&#61;(q,)) # 声明发送进程recv_process &#61; Process(target&#61;recv, args&#61;(q,)) # 声明接收进程send_process.start() # 开启发送进程recv_process.start() # 开启接收进程send_process.join() # 等待发送进程结束recv_process.terminate() #强制关闭接收进程

Queue通信案例

Pipe管道案例

from multiprocessing import Process, Pipedef fun(conn):conn.send("this is child_process") #向父进程发送数据
conn.close()if __name__ &#61;&#61; "__main__":parent_conn, child_conn &#61; Pipe() #声明一个pipe管道&#xff0c;拥有两个返回值&#xff0c;分别代表通信的两端p &#61; Process(target&#61;fun, args&#61;(child_conn,))p.start()print(parent_conn.recv()) #接收子进程发送的数据p.join()

Pipe通信案例

3.3 进程同步

from multiprocessing import Process, Lockdef fun(lock, i):lock.acquire()try:print(&#39;This is process &#39;, i)finally:lock.release()if __name__ &#61;&#61; &#39;__main__&#39;:lock &#61; Lock()for i in range(10):Process(target&#61;fun, args&#61;(lock, i)).start()

进程同步案例

3.4 进程池 Pool

进程池内部维护一个进程序列&#xff0c;当使用时&#xff0c;则去进程池中获取一个进程&#xff0c;如果进程池序列中没有可供使用的进进程&#xff0c;那么程序就会等待&#xff0c;直到进程池中有可用进程为止。

from multiprocessing import Process, Pool
import timedef fun(i):time.sleep(2)return i*idef callback_fun(res):print(&#39;return result:&#39;, res)if __name__ &#61;&#61; "__main__":pool &#61; Pool(5) #定义进程池&#xff0c;最多有5个进程for i in range(10):pool.apply_async(func&#61;fun, args&#61;(i,), callback&#61;callback_fun) #异步调用进程池&#xff0c;传入启用函数&#xff0c;参数&#xff0c;回调函数
pool.close()pool.join() # 进程池中进程执行完毕后再关闭,一定要加上&#xff0c;不然不会运行

线程池案例

转:https://www.cnblogs.com/CodeHu/p/8488980.html



推荐阅读
  • 深入理解Java虚拟机的并发编程与性能优化
    本文主要介绍了Java内存模型与线程的相关概念,探讨了并发编程在服务端应用中的重要性。同时,介绍了Java语言和虚拟机提供的工具,帮助开发人员处理并发方面的问题,提高程序的并发能力和性能优化。文章指出,充分利用计算机处理器的能力和协调线程之间的并发操作是提高服务端程序性能的关键。 ... [详细]
  • Python已成为全球最受欢迎的编程语言之一,然而Python程序的安全运行存在一定的风险。本文介绍了Python程序安全运行需要满足的三个条件,即系统路径上的每个条目都处于安全的位置、"主脚本"所在的目录始终位于系统路径中、若python命令使用-c和-m选项,调用程序的目录也必须是安全的。同时,文章还提出了一些预防措施,如避免将下载文件夹作为当前工作目录、使用pip所在路径而不是直接使用python命令等。对于初学Python的读者来说,这些内容将有所帮助。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 本文介绍了如何使用python从列表中删除所有的零,并将结果以列表形式输出,同时提供了示例格式。 ... [详细]
  • 本文介绍了在使用Python中的aiohttp模块模拟服务器时出现的连接失败问题,并提供了相应的解决方法。文章中详细说明了出错的代码以及相关的软件版本和环境信息,同时也提到了相关的警告信息和函数的替代方案。通过阅读本文,读者可以了解到如何解决Python连接服务器失败的问题,并对aiohttp模块有更深入的了解。 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • 基于dlib的人脸68特征点提取(眨眼张嘴检测)python版本
    文章目录引言开发环境和库流程设计张嘴和闭眼的检测引言(1)利用Dlib官方训练好的模型“shape_predictor_68_face_landmarks.dat”进行68个点标定 ... [详细]
  • 本文介绍了在处理不规则数据时如何使用Python自动提取文本中的时间日期,包括使用dateutil.parser模块统一日期字符串格式和使用datefinder模块提取日期。同时,还介绍了一段使用正则表达式的代码,可以支持中文日期和一些特殊的时间识别,例如'2012年12月12日'、'3小时前'、'在2012/12/13哈哈'等。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • Python操作MySQL(pymysql模块)详解及示例代码
    本文介绍了使用Python操作MySQL数据库的方法,详细讲解了pymysql模块的安装和连接MySQL数据库的步骤,并提供了示例代码。内容涵盖了创建表、插入数据、查询数据等操作,帮助读者快速掌握Python操作MySQL的技巧。 ... [详细]
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
  • Python教学练习二Python1-12练习二一、判断季节用户输入月份,判断这个月是哪个季节?3,4,5月----春 ... [详细]
  • 从批量eml文件中提取附件的Python代码实现方法
    本文介绍了使用Python代码从批量eml文件中提取附件的实现方法,包括获取eml附件信息、递归文件夹下所有文件、创建目的文件夹等步骤。通过该方法可以方便地提取eml文件中的附件,并保存到指定的文件夹中。 ... [详细]
  • Window10+anaconda+python3.5.4+ tensorflow1.5+ keras(GPU版本)安装教程 ... [详细]
author-avatar
K_M_睡到自然醒cES_881
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有