线程

  线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。
————目录————:

  • 多线程的基本使用
  • 查看线程名称及数量
  • 线程的参数传递
  • 线程的执行顺序
  • 守护线程
  • 线程的全局变量
  • 互斥锁
  • 死锁
  • 自定义线程

1.多线程的基本使用
(1)导入threading模块

import threading

(2)创建threading.Thread实例对象

对象名 = threading.Thread(target=函数名, args=参数)

参数的传递方式一般为元组或字典,下面会详细解释
(3)线程启动

对象名.start()

例:

# 1.导入模块
import threading
import timedef sing():for i in range(3):print("正在唱歌...%d"%i)time.sleep(1)def dance():for i in range(3):print("正在跳舞...%d"%i)time.sleep(1)if __name__ == '__main__':print('---开始---')# 2.创建threading.Thread实例对象t1 = threading.Thread(target=sing)t2 = threading.Thread(target=dance)# 3.线程启动t1.start()t2.start()print('---结束---')


小结:
(1)使用多线程并发的操作,花费时间要短很多
(2)当调用start()时,才会真正的创建线程,并且开始执行
(3)主线程:mainThread,Main函数或者程序主入口,都可以称为主线程
(4)子线程:Thread-x 使用 threading.Thread() 创建出来的都是子线程
(5)主线程会在子线程运行结束后结束

2.查看线程名称及数量

方法 描述
threading.current_thread 返回当前线程名称
thread_list = threading.enumerate() 获取所有正在活跃的线程,返回值是一个列表

len(thread_list):活跃线程列表的长度,即线程数量

小结:
(1)每个线程都有一个唯一标示符,来区分线程中的主次关系
(2)每个线程默认有一个名字,尽管上面的例子中没有指定线程对象的name,但是python会自动为线程指定一个名字。
(3)线程数量:主线程数 + 子线程数

3.线程的参数传递
(1)元祖传参:args = (参数1,参数2,…)
注意:如果只有一个参数,应写为args=(参数,),逗号不可省略,证明他是一个元组
(2)字典传参:kwargs = {“a”: 10, “b”:100,….}
(3)混合使用:args = (参数1,), kwargs = {“b”:100,…….}

4.线程的执行顺序
  多线程程序的执行顺序是不确定的。当执行到sleep语句时,线程将被阻塞(Blocked),到sleep结束后,线程进入就绪(Runnable)状态,等待调度。而线程调度将自行选择一个线程执行。可通过time.sleep()方式来调节线程的执行顺序。
  
5.守护线程
  如果在程序中将子线程设置为守护线程,则该子线程会在主线程结束时自动退出,设置方式为thread.setDaemon(True),要在thread.start()之前设置,默认是false的,也就是主线程结束时,子线程依然在执行。
设置守护线程:

线程名.setDaemon(True)

设置守护线程后,主线程结束,子线程也结束。
例:

import time
import threadingdef work():for i in range(10):print("正在执行work...", i)time.sleep(0.5)if __name__ == '__main__':# 创建线程对象t1 = threading.Thread(target=work)# 让子线程守护主线程# setDaemon() 设置子线程守护主线程,当主线程结束的时候,子线程也要结束t1.setDaemon(True)# 启动子线程t1.start()# 主线程睡眠 2秒time.sleep(2)print("Game Over")# 程序要退出exit()


6.线程的全局变量
  线程间可以共享全局变量
例:

import threading
import time
n = 0def fun1():global nn += 1print("fun1:n=%d" % n)def fun2():global nn += 1print("fun2:n=%d" % n)if __name__ == '__main__':f1 = threading.Thread(target=fun1)f2 = threading.Thread(target=fun2)f1.start()f2.start()time.sleep(1)print(n)


7.互斥锁
异步方式:多任务间执行不分先后顺序,可同时进行,有多个主线。
同步方式:多任务间执行有先后顺序,不可同时进行,只有一个主线。

  当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制,否则会导致错误,此时需要使用互斥锁,修改数据时现将资源锁定,修改后再解锁资源。
  
用法:
创建:lock = threading.Lock()
锁定:lock.acquire()
解锁:lock.release()
注意:如果锁定时当前资源已锁定,会进入阻塞状态,直到这个锁被解锁。
例:
异步方式修改共享资源:

import threading
import time
n = 0def fun1():global nfor i in range(1000000):n += 1print("fun1:n=%d" % n)def fun2():global nfor i in range(1000000):n += 1print("fun2:n=%d" % n)if __name__ == '__main__':f1 = threading.Thread(target=fun1)f2 = threading.Thread(target=fun2)f1.start()f2.start()time.sleep(2)print(n)

执行结果:

此时会发现,结果并不是预期的n=2000000,应为异步方式同时修改某个共享资源可能会发生错误,此时需要给资源上锁。

同步方式修改共享资源:

import threading
import time
n = 0def fun1():global nfor i in range(1000000):lock.acquire()n += 1lock.release()print("fun1:n=%d" % n)def fun2():global nfor i in range(1000000):lock.acquire()n += 1lock.release()print("fun2:n=%d" % n)if __name__ == '__main__':f1 = threading.Thread(target=fun1)f2 = threading.Thread(target=fun2)lock = threading.Lock()f1.start()f2.start()time.sleep(2)print(n)

执行结果:

可以看出,给资源上锁进行同步控制后,可以使多线程正确的修改共享数据。

8.死锁:
  在线程间共享多个资源时,有两个线程分别占有一部分资源并且同时等待对 方的资源,会造成死锁,造成程序停止响应。所以设计程序时应尽量避免死锁的发生。
死锁的一个简单例子:

import threading
import time
lock1 = threading.Lock()  # 创建一个互斥锁
lock2 = threading.Lock()  # 创建一个互斥锁def fun1():lock1.acquire()print("fun1 lock1锁住")# 线程停止0.5s,等待另一个锁上锁time.sleep(0.5)lock2.acquire()print("fun1 lock2锁住")lock1.release()lock2.release()def fun2():lock2.acquire()print("fun2 lock2锁住")# 线程停止0.5s,等待另一个锁上锁time.sleep(0.5)lock1.acquire()print("fun2 lock1锁住")lock2.release()lock1.release()if __name__ == '__main__':t1 = threading.Thread(target=fun1)  # 创建一个线程对象t2 = threading.Thread(target=fun2)  # 创建一个线程对象t1.start()t2.start()

程序会卡死,无法进行下一步:

9.自定义线程
  通过使用threading模块能完成多任务的程序开发,为了让每个线程的封装性更完美,所以使用threading模块时,往往会定义一个新的子类class,只需要继承threading.Thread,重写某些方法。
例:

import threading
import time"""自定义线程类:1)定义一个类,让该类继承 threading.Thread2) 重写父类的 run() 方法3)使用线程类,创建线程对象4)通过线程对象的start() 方法,启动线程class MyThread():def run(self):...def start(self):self.run()"""# MyThread 就是一个线程类
class MyThread(threading.Thread):def __init__(self, num):# 调用当前类的父类的构造方法super().__init__()# 把 num 保存到实例属性self.num = num# 重写 父类的run方法def run(self):for i in range(self.num):# self.name 父类属性,保存的是当前线程的名称print("Mythread-run 正在运行", i, self.name)time.sleep(0.5)# 继承了父类的 start()# def start(self):#     self.run()if __name__ == '__main__':# 实例化对象mythread = MyThread(5)# 启动线程mythread.start()

运行结果:

  python的threading.Thread类有一个run方法,用于定义线程的功能函数,可以在自己的线程类中覆盖该方法。而创建自己的线程实例后,通过Thread类的start方法,可以启动该线程,交给python虚拟机进行调度,当该线程获得执行的机会时,就会调用run方法执行线程。

Python高级——多线程(threading)相关推荐

  1. python的多线程threading

    多线程threading 1.Thread创建线程: 上代码: #!/usr/bin/env python3import threading import timedef A():t_name = t ...

  2. python爬虫———多线程threading模块爬取抖音用户信息

    爬虫背景: 由于原来的数据库中有1.5亿左右的用户id,但是其中有1.2亿的用户资料是不完整的(没有粉丝数量,点赞数量等,算是无用数据),现在老板要求将这些没有资料的用户更新信息,咋办? 刚开始的想法 ...

  3. Python多线程 Threading

    1.介绍 多线程是加速程序计算的有效方式,Python的多线程模块threading上手快速简单,从这节开始我们就教大家如何使用它. 2.添加线程 本节我们来学习threading模块的一些基本操作, ...

  4. mofan-python多线程Threading

    1.什么是多线程 在一个程序运行过程中,能够在同一时刻运行多个不同的操作. 单线程->串行 多线程->并行 多线程是加速程序计算的有效方式,Python的多线程模块threading上手快 ...

  5. python3 多线程 threading.local 代理_threading.local的作用?Python每日3题(多线程专题)...

    这里是Python7编程挑战-多线程专题! 每天学习3个问题,包括初级,中级,高级问题各1个. 今天是第5天!一起来呀,就7天!每日3题是麦叔的面试系列专题之一,每天包括初级,中级,高级难度题目各一道 ...

  6. python多线程threading

    本文通过 4个example 介绍python中多线程package -- threading的常用用法, 包括调用多线程, 同步队列类Queue, Ctrl+c结束多线程. example1. 调用 ...

  7. python进阶 多线程编程 —— threading和queue库实现多线程编程

    python进阶 多线程编程 -- threading和queue库实现多线程编程) 摘要 多线程实现逻辑封装 模型参数选择实例 摘要 本文主要介绍了利用python的 threading和queue ...

  8. python守护多线程_Python多线程Threading、子线程与守护线程实例详解

    线程Threading: python中多线程需要使用threading模块 线程的创建与运行: 1.直接调用threading的Thread类: 线程的创建:线程对象=thread.Thread(t ...

  9. Python多线程threading和多进程multiprocessing的区别及代码实现

    1. 多线程threading import time from threading import Threaddef thread_read(data):while True:print('read ...

最新文章

  1. 某产品经理炫耀:3年跳槽3次,月薪从8k涨到38k,跳槽涨薪最快!
  2. 计算机毕业生“一看就想留下”的简历
  3. 从MSSQL添加对Oracle的链接服务器的存储过程
  4. PAT A1030 动态规划
  5. mongodb启动不了:child process failed, exited with err
  6. 通过邮箱验证注册——.net代码
  7. CDE桌面环境中自动启动应用程序图形界面
  8. (二)Docker中以redis.conf配置文件启动Redis
  9. JavaScript——以简单的方式理解闭包
  10. 配置网站之后500.19错误
  11. 谷歌新玩具Vision Kit,带你DIY一个能识别千种物体的AI摄像头
  12. think php5关联模型,thinkphp5中关联模型的定义与使用方法
  13. python画反比例函数_反比例光滑支撑向量机
  14. 安师大计算机专业分数线,安徽师范大学
  15. 小学生学计算机编程实例,用日常生活小例子来教孩子学编程
  16. 【分层图最短路】P2939 [USACO09FEB]Revamping Trails G
  17. JAVA微信开发-新手接入指南
  18. python在冒号处显示语法错误_python冒号错误语法无效
  19. mySql 修改字段属性
  20. python数据分析实战之信用卡违约风险预测

热门文章

  1. mysql报错Attempted to open a previously opened tablespace的解决办法
  2. 德佑地产房产经纪人区域总监访谈:有肌肉,更有内涵!
  3. 终于知道以后该咋办了!
  4. Oracle性能调优之--Buffer cache 的调整与优化
  5. VMware安装Centos7详细过程
  6. C语言圈叉游戏,圈叉棋小游戏的简单实现代码
  7. while语句的使用
  8. MySQL报错 Packet for query is too large,server向mysql发送的数据包大小超过mysql限制
  9. 函数式编程 -- 函数组合
  10. 【Python】pyinstaller安装失败的解决办法