Python每日笔记13(线程)

zz/2024/7/13 10:40:52

本次内容:线程

>> Python每日笔记—目录 <<

线程

多线程的使用

  1. Thread()
    group:线程组,目前只能使用None
    target:执行的目标任务名
    *args:以元组的方式给执行任务进行传参
    **kwargs:以字典的方式进行传参
    name:线程名称,一般不进行设置
# 导入线程模块
import threading
import time
def sing():# 获取当前线程current_thread()current_thread = threading.current_thread()print("sing:", current_thread)# 休眠sleep   打印10次后休眠当前线程for i in range(5):print("唱歌中。。。")time.sleep(0.5)def dance():# 获取当前线程current_thread = threading.current_thread()print("dance:", current_thread)# 休眠sleep   打印10次后休眠当前线程for i in range(3):print("跳舞中。。。")time.sleep(0.7)# 调用一下
#sing()  # sing: <_MainThread(MainThread, started 11152)>if __name__ == '__main__':# 获取当前线程current_thread = threading.current_thread()print("main_thread",current_thread) # main_thread <_MainThread(MainThread, started 3304)># 创建子线程,分别执行sing()和dance()内容sing_thread = threading.Thread(target=sing, name="sing_thread")dance_thread = threading.Thread(target=dance, name="dance_thread")# 启动线程# 运行结果交替输出,线程在争夺资源sing_thread.start()dance_thread.start()

线程参数

  1. 以元素的方式进行传参,元素里面元素的顺序和参数的参数顺序保持一致
  2. 以字典的形式进行传参,保证字典里面的key和函数参数名称一致
import threading
def show_info(name, age):print("name:%s age%d" % (name, age))if __name__ == '__main__':'''1、以元素的方式进行传参,元素里面元素的顺序和参数的参数顺序保持一致2、以字典的形式进行传参,保证字典里面的key和函数参数名称一致'''sub_thread = threading.Thread(target=show_info, args=('张三', 30))sub_thread.start()sub_thread = threading.Thread(target=show_info, kwargs={'name': "李四", 'age': 20})sub_thread.start()

线程的另外一种创建方式 _thread

import _thread
import time
# 为线程定义一个函数
def print_time(thread_name, delay):count = 0while count < 5:time.sleep(delay)count += 1print("%s:%s"%(thread_name,time.ctime(time.time())))# 创建两个线程
try:_thread.start_new_thread(print_time, ("Thread-1", 2))_thread.start_new_thread(print_time, ("Thread-2", 4))
except:print("Error:无法启动线程")
while 1:pass

start()启动线程

  1. 使用threading模块创建线程,我们可以通过threading。
  2. Thread继承创建一个线程的子类并且实例化之后调用start()方法启动方法
import threading
import timeexitFlag = 0    # 判断是否退出的变量
class my_thread(threading.Thread):def __init__(self, threadID, name, counter):threading.Thread.__init__(self)self.threadID = threadIDself.name = nameself.counter = counterdef run(self):  # 重写父类中的run方法print("开始线程:"+ self.name)print_time(self.name, self.counter, 5)print("退出线程:"+self.name)# self.counter传给delay(休眠时间)     counter = 5
def print_time(thread_name, delay, counter):while counter:if exitFlag:thread_name.exit()time.sleep(delay)print("%s:%s"%(thread_name,time.ctime(time.time())))counter -= 1# 创建新线程
thread1 = my_thread(1, 'Thread-1', 1)
thread2 = my_thread(2, 'Thread-2', 2)
thread1.start() # 执行的是run方法的内容!!
thread2.start()

守护线程

  1. 主线程会等待子线程结束之后再结束
    如果不想结束子线程怎么办?
  2. 解决方法:把子线程改成守护线程即可(setDaemon(true))
import threading
import time
def task():for i in range(5):print("任务执行中。。。%d" % i)time.sleep(0.5)if __name__ == '__main__':'''创建一个子线程'''sub_thread = threading.Thread(target=task)sub_thread.setDaemon(True)  # 将该线程设置为守护线程sub_thread.start()  # 启动线程time.sleep(1)print("over")

线程共享全局变量

join(): 使某线程占用资源,直到此线程结束

import threading
import time
# 定义一个全局变量
g_list = []
# 添加数据的任务
def add_data():for i in range(3):g_list.append(i)print("add:",i)time.sleep(0.3)print("添加数据完成", g_list)
# 读取数据的任务
def read_data():print("read:", g_list)if __name__ == '__main__':# 创建添加数据的子线程add_thread = threading.Thread(target=add_data)read_thread = threading.Thread(target=read_data)add_thread.start()# 让当前线程(主线程)等待添加数据的子线程完成以后,代码再继续执行add_thread.join()read_thread.start()

多线程全局变量案例

多线程操作全局变量的问题:

  1. 创建一个变量 num
  2. 第一个线程执行完之后,num的值递增到10000(每次递增1个单位)
  3. 第二个线程执行完之后,num的值递增到20000(每次递增1个单位)
import threading
import time
num = 0def add1():global numfor i in range(10000):num += 1# time.sleep(0.0001)    时间间隔print("num:", num)print("----num----", num)if __name__ == '__main__':add1_thread = threading.Thread(target=add1)add2_thread = threading.Thread(target=add1)add1_thread.start()add1_thread.join()add2_thread.start()

线程锁

创建锁:lock = threading.Lock()
上锁:lock.acquire()
互斥锁:

  1. 可以保证一个时间段只有一个线程去执行代码,能够保证全局变量的数据没有问题
  2. 线程等待和互斥都是把多个任务改成单个任务去执行。
  3. 好处是能够保证数据的准确性,但执行的性能会下降

案例一:

案例中,task1中使用了锁,使得task1线程可以独占资源,task2需要等待task1结束后才开始执行。

import threading
g_num = 0
# 创建一个互斥锁
lock = threading.Lock() # Lock()本质上是一个函数,通过调用该函数可以创建一个互斥锁对象
# 创建一个函数,执行100万次任务
def task1():# 上锁lock.acquire()for i in range(10):global g_numg_num += 1print("task1=", g_num)# 数据计算完成# print("task1=", g_num)def task2():for i in range(10):global g_numg_num -= 1print("task2=", g_num)# 数据计算完成# print("task2=", g_num)if __name__ == '__main__':# 创建两个子线程oneThread = threading.Thread(target=task1)twoThread = threading.Thread(target=task2)# 使用互斥锁的方式,而不是用线程等待的方式,只执行一个线程oneThread.start()twoThread.start()# 输出结果:两个线程不再抢夺,task1循环执行完之后才会执行task2的循环

案例二:

import threading
# 创建互斥锁
lock = threading.Lock()
def get_value(index):# 上锁lock.acquire()my_list = [4, 6, 8]# 判断下标是否越界if index >= len(my_list):print("下标越界", index)# 不释放资源,后面无法执行lock.release()return# 根据下标去取值value = my_list[index]print(value)# 如果不释放,只打印一次value,并且把资源锁住# 释放后,会打印出所有的valuelock.release()
if __name__ == '__main__':for i in range(10):# 每循环一次就创建一个子线程sub_thread = threading.Thread(target=get_value,args=(i,))sub_thread.start()

如果这篇文章对你有帮助的话,点个赞呗~


http://www.ngui.cc/zz/2732109.html

相关文章

爬虫网络库(5.requests网络库)

这里写目录标题 Request网络库介绍5.1 request使用案例15.2 get方法5.3 设置请求头headers5.4 get_binary方法5.5 使用post方法发送post请求5.6 response请求响应结果5.7 uploadfile上传文件5.8 设置Cookie5.9 使用Session对象5.10 SSL签名证书5.11 proxy设置HTTP/HTTPS的代理5…

vue中虚拟DOM到真实DOM大概转化过程

let vnode {tagname: div,attrs: {id: 1,class: active},content: hello } // 虚拟DOM到真实DOM的大概转换过程 let div document.createElement(vnode.tagname) for (let key in vnode.attrs) {div.setAttribute(key, vnode.attrs[key]) } div.innerHMTL vnode.content

SQLAlchemy连接MySQL数据库的方法

代码如下&#xff1a; 在create_engine中输入的是一个连接字符串。在使用python的SQLAlchemy时&#xff0c;连接字符串的格式如下&#xff1a; 数据库产品名连接工具名&#xff1a;//用户名&#xff1a;密码数据库IP地址&#xff1a;数据库端口号/数据库名称&#xff1f;chars…

springBoot使用druid数据库连接池以及logback,并开启慢sql记录输出到指定的日志文件

该文主要记录下自己使用过程&#xff0c;以后用到可以看看&#xff0c;我的springBoot版本是2.2.1&#xff0c;2以上应该都没问题 1.首先添加好需要的依赖包&#xff1a; <!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-…

重温经典:Windows1.0系统体验和尝试自己编写Windows1.0系统

相关说明 如果你觉得文章含有侵权部分,可以联系CSDN私聊,我会适当修改。 未经允许,不得转载,如需转载,请CSDN私聊。 Windows Windows,意思是窗口,窗户。当然,他也是一个操作系统的名字。 1983年,由比尔盖茨建立的Microsoft,也就是微软公司,开始研制Windows操作系统…

读书笔记_mysql必知必会_27_全球化和本地化

目录 字符集和校对顺序 使用字符集和校对顺序 字符集和校对顺序 数据库表被用来存储和检索数据。不同的语言和字符集需要以不同的方式存储和检索。因此&#xff0c;MySQL 需要适应不同的字符集&#xff08;不同的字母和字符&#xff09;&#xff0c;适应不同的排序和检索数据…

Serializable和Externalizable浅析

Java序列化是指把Java对象转换为字节序列的过程&#xff1b;而Java反序列化是指把字节序列恢复为Java对象的过程。从而达到网络传输、本地存储的效果。 本文主要要看看JDK中使用Serializable和Externalizable接口来完成Java对象序列化&#xff0c;并给出部分属性序列化的几种方…

java8新特性_12_Stream练习

public class TestStreamApi04lianxi {List<Employee> emps Arrays.asList(new Employee("张三", 18,9999.99, Status.FREE),new Employee("李四", 38,5555.99, Status.BUSY),new Employee("王五", 50,6666.66, Status.VOCATION),new Emp…

《并发编程的艺术》第一章 并发编程的挑战

1.1 上下文切换 CPU 通 过时间 片分配算法来循 环执 行任 务 &#xff0c;当前任 务执 行一个 时间 片后会切 换 到下一个 任务 。但是&#xff0c;在切 换 前会保存上一个任 务 的状 态 &#xff0c;以便下次切 换 回 这 个任 务时 &#xff0c;可以再加 载这 个任务 的状 态…

保障消息100%投递成功、消息幂等性

一、前言 我们小伙伴应该都听说够消息中间件MQ&#xff0c;如&#xff1a;RabbitMQ&#xff0c;RocketMQ&#xff0c;Kafka等。引入中间件的好处可以起到抗高并发&#xff0c;削峰&#xff0c;业务解耦的作用。 如上图&#xff1a; &#xff08;1&#xff09;订单服务投递消息…