博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【记录】python多线程的使用 线程同步(LOCK和RLOCK) python与mysql数据库交互实现增加和查找 python的格式化输出
阅读量:3903 次
发布时间:2019-05-23

本文共 8984 字,大约阅读时间需要 29 分钟。

文章目录


多线程:

_thread模块

例一

import _threadimport time# 为线程定义一个函数def print_time(threadName, delay):    count = 0    while count < 5:        time.sleep(delay)        count += 1        print("%s: %s" % (threadName, 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

例二:

import _threadfrom time import sleepfrom datetime import datetimedate_time_format='%y-%M-%d %H:%M:%S'def date_time_str(date_time):    return datetime.strftime(date_time, date_time_format)def loop_one():    print(f'+++线程一开始于:{
date_time_str(datetime.now())}') print('+++线程一休眠4秒') sleep(4) print(f'+++线程一休眠结束,结束于:{
date_time_str(datetime.now())}')def loop_two(): print(f'***线程二开始时间:{
date_time_str(datetime.now())}') print('***线程二休眠2秒') sleep(2) print(f'***线程二休眠结束,结束时间:{
date_time_str(datetime.now())}')def main(): print(f'------所有线程开始时间:{
date_time_str(datetime.now())}') _thread.start_new_thread(loop_one, ()) _thread.start_new_thread(loop_two, ()) sleep(6) print(f'------所有线程结束时间:{
date_time_str(datetime.now())}')if __name__ == '__main__': main()

在这里插入图片描述

主线程一旦运行结束,就关闭运行着的其他两个线程。这可能造成主线程过早或过晚退出,这时就要使用线程锁,主线程可以在两个子线程都退出后立即退出。 示例代码如下

import _threadfrom time import sleepfrom datetime import datetimeloops=[4, 2]date_time_format='%y-%M-%d %H:%M:%S'def date_time_str(date_time):    return datetime.strftime(date_time, date_time_format)def loop(n_loop, n_sec, lock):    print(f'线程({
n_loop})开始执行:{
date_time_str(datetime.now())},先休眠({
n_sec})秒') sleep(n_sec) print(f'线程({
n_loop})休眠结束,结束于:{
date_time_str(datetime.now())}') lock.release()def main(): print('---所有线程开始执行...') locks=[] n_loops=range(len(loops)) for i in n_loops: lock=_thread.allocate_lock() lock.acquire() locks.append(lock) for i in n_loops: _thread.start_new_thread(loop, (i, loops[i], locks[i])) for i in n_loops: while locks[i].locked(): pass print(f'---所有线程执行结束:{
date_time_str(datetime.now())}')if __name__ == '__main__': main()

threading模块:

_thread模块不支持守护线程,当主线程退出时,所有子线程无论是否在工作,都会被强行退出。threading模块支持守护线程,守护线程一般是一个等待客户请求的服务器,如果没有客户提出请求,就一直等着。如果设定一个线程为守护线程,就表示这个线程不重要,在进程退出时,不用等待这个线程退出。如果主线程退出时不用等待子线程完成,就要设定这些线程的daemon属性,即在线程Thread.start()开始前,调用setDaemon()函数设定线程的daemon标志(Thread.setDaemon(True)),表示这个线程“不重要”。如果一定要等待子线程执行完成再退出主线程,就什么都不用做或显式调用Thread.setDaemon(False)以保证daemon标志为False,可以调用Thread.isDaemon()函数判断daemon标志的值。新的子线程会继承父线程的daemon标志,主线程在所有非守护线程退出后才会结束,即进程中没有非守护线程存在时才结束。

例子:

import threadingfrom time import sleepfrom datetime import datetimeloops=[4, 2]date_time_format='%y-%M-%d %H:%M:%S'def date_time_str(date_time):    return datetime.strftime(date_time, date_time_format)def loop(n_loop, n_sec):    print(f'线程({
n_loop})开始执行:{
date_time_str(datetime.now())},先休眠({
n_sec})秒') sleep(n_sec) print(f'线程({
n_loop})休眠结束,结束于:{
date_time_str(datetime.now())}')def main(): print(f'---所有线程开始执行:{
date_time_str(datetime.now())}') threads=[] n_loops=range(len(loops)) for i in n_loops: t=threading.Thread(target=loop, args=(i, loops[i])) threads.append(t) for i in n_loops: # start threads threads[i].start() for i in n_loops: # wait for all threads[i].join() # threads to finish print(f'---所有线程执行结束于:{
date_time_str(datetime.now())}')if __name__ == '__main__': main()

在这里插入图片描述

附自己修改后的代码:

import threadingfrom time import sleepfrom datetime import datetimeloops=[2, 2]date_time_format='%y-%M-%d %H:%M:%S'def date_time_str(date_time):    return datetime.strftime(date_time, date_time_format)def loop(n_loop, n_sec):    print(f'线程({
n_loop})开始执行:{
date_time_str(datetime.now())},先休眠({
n_sec})秒') sleep(n_sec) print(f'线程({
n_loop})休眠结束,结束于:{
date_time_str(datetime.now())}')def begin(n_loop,sec): print(f'线程{
n_loop}开始执行:{
date_time_str(datetime.now())}') print("begin") sleep(sec) print(f'{
n_loop}休眠结束,结束于:{
date_time_str(datetime.now())}')def main(): print(f'---所有线程开始执行:{
date_time_str(datetime.now())}') threads=[] n_loops=range(len(loops)) t=threading.Thread(target=loop, args=(1, loops[0])) threads.append(t) m=threading.Thread(target=begin,args=(2,loops[1])) threads.append(m) for i in n_loops: # start threads threads[i].start() for i in n_loops: # wait for all threads[i].join() # threads to finish print(f'---所有线程执行结束于:{
date_time_str(datetime.now())}')if __name__ == '__main__': main()

线程同步(LOCK和RLOCK)

如果多个线程共同修改某个数据,就可能会出现不可预料的结果。为了保证数据的正确性,需要对多个线程进行同步。 使用Thread对象的Lock和RLock可以实现简单的线程同步,这两个对象都有acquire方法和release方法。对于每次只允许一个线程操作的数据,可以将操作放到acquire和release方法之间。 多线程的优势在于可以同时运行多个任务,但当线程需要共享数据时,可能存在数据不同步的问题。 考虑这样一种情况:一个列表里所有元素都是0,线程set从后向前把所有元素改成1,而线程print负责从前往后读取列表并输出。

线程set开始改的时候,线程print可能就来输出列表了,输出就成了一半0一半1,这就是数据不同步的问题。为了避免这种情况,引入了锁的概念。 锁有两种状态——锁定和未锁定。当一个线程(如set)要访问共享数据时,必须先获得锁定;如果已经有别的线程(如print)获得锁定了,就让线程set暂停,也就是同步阻塞;等到线程print访问完毕,释放锁以后,再让线程set继续。 经过这样的处理,输出列表时要么全部输出0,要么全部输出1,不会再出现一半0一半1的尴尬场面。

示例代码:

import threadingfrom time import sleepfrom datetime import datetime date_time_format='%y-%M-%d %H:%M:%S' class MyThread (threading.Thread):    def __init__(self, threadID, name, counter):        threading.Thread.__init__(self)        self.threadID=threadID        self.name=name        self.counter=counter     def run(self):        print(f"开启线程: {
self.name}") # 获取锁,用于线程同步 threadLock.acquire() print_time(self.name, self.counter, 3) # 释放锁,开启下一个线程 threadLock.release()  def date_time_str(date_time): return datetime.strftime(date_time, date_time_format)  def print_time(threadName, delay, counter): while counter: sleep(delay) print(f"{
threadName}: {
date_time_str(datetime.now())}") counter -= 1  def main(): # 创建新线程 thread1=MyThread(1, "Thread-1", 1) thread2=MyThread(2, "Thread-2", 2)  # 开启新线程 thread1.start() thread2.start()  # 添加线程到线程列表 threads.append(thread1) threads.append(thread2)  # 等待所有线程完成 for t in threads: t.join() print("退出主线程")  if __name__ == "__main__": threadLock=threading.Lock() threads=[] main()  

和mysql交互:

增加和查询操作:

import pymysqlimport timepymysql.install_as_MySQLdb()from sqlalchemy import create_engine,text#定义数据库属性hostname = '127.0.0.1'port = '3308'database = 'data1'username = 'heziyi'pwd = '123456'dburl = 'mysql+mysqldb://{}:{}@{}:{}/{}'.format(username,pwd,hostname,port,database)timenow= time.strftime('%Y-%m-%d',time.localtime(time.time()))print(timenow)#创建数据库连接对象engine = create_engine(dburl,echo=True)with engine.connect() as con: # rs = con.execute('SELECT 1')  # con.execute(text("select 1 "))  sql = 'INSERT INTO data1.wash VALUES(10,\'15\',\'175\',\'9\',\'19.4\',\'2021-05-24\');'  result = con.execute(sql )  result = con.execute('select * from wash')  print(result.fetchall())

在这里插入图片描述

查询某一列:

result = con.execute('select times,average,Time from wash')  print(result.fetchall())

结果:

[(‘4’, 30.5, datetime.date(2021, 5, 18)), (‘5’, 28.4, datetime.date(2021, 5, 20)), (‘6’, 26.7, datetime.date(2021, 5, 21)), (‘7’, 26.0, datetime.date(2021, 5, 22)), (‘8’, 25.7, datetime.date(2021, 5, 23)), (‘9’, 19.4, datetime.date(2021, 5, 24))]

格式化插入(传入变量的方式):

timenow= time.strftime('%Y-%m-%d',time.localtime(time.time()))#创建数据库连接对象engine = create_engine(dburl,echo=True)with engine.connect() as con:  sql = 'INSERT INTO data1.wash VALUES(11,\'15\',\'175\',\'9\',\'19.4\',\'{}\');'.format(timenow)

附:python的格式化输出

多个格式化

‘b’ - 二进制。将数字以2为基数进行输出。

‘c’ - 字符。在打印之前将整数转换成对应的Unicode字符串。
‘d’ - 十进制整数。将数字以10为基数进行输出。
‘o’ - 八进制。将数字以8为基数进行输出。
‘x’ - 十六进制。将数字以16为基数进行输出,9以上的位数用小写字母。
‘e’ - 幂符号。用科学计数法打印数字。用’e’表示幂。
‘g’ - 一般格式。将数值以fixed-point格式输出。当数值特别大的时候,用幂形式打印。
‘n’ - 数字。当值为整数时和’d’相同,值为浮点数时和’g’相同。不同的是它会根据区域设置插入数字分隔符。
‘%’ - 百分数。将数值乘以100然后以fixed-point(‘f’)格式打印,值后面会有一个百分号。

print('{0:b}'.format(3))print('{0:d}'.format(3))print('{0:o}'.format(3))print('{0:x}'.format(3))

在这里插入图片描述

name = ‘jack’
age = 18
sex = ‘man’
job = “IT”
salary = 9999.99

print(f’my name is {name.capitalize()}.’)

print(f’I am {age:*^10} years old.’)
print(f’I am a {sex}’)
print(f’My salary is {salary:10.3f}’)

结果

my name is Jack.
I am 18 years old.
I am a man
My salary is 9999.990

附录

关于python运行多线程的问题:

1)Python多线程的效率怎么样
答:Python有全锁局的存在(同一时间只能有一个线程执行),并不能利用多核优势。如果你的多线程进程是CPU密集型的,多线程就不能带来效率的提升,相反还可能因为线程的频繁切换导致效率下降。如果是IO密集型,多线程进程就可以利用IO阻塞等待时的空闲时间执行其他线程,从而提升效率。 (2)既然Python解释器是单线程的,还有进行多线程编程的必要吗
答:多线程最开始不是用来解决多核利用率问题的,而是用来解决IO占用时CPU闲置的问题。 多线程可以用来解决阻塞问题,可以做事件响应机制(或者类似信号槽的问题)。如果运行瓶颈不是在CPU运算而是在IO(网络)上,多线程显然很划算。 能产生IO阻塞的情况很多,如网络、磁盘等。当发生阻塞时,Python是不耗CPU的,此时如果只有一个线程就没法处理其他事情了。对于有IO阻塞的环境,多线程可能让你的CPU跑到100%。 另一个用处来自于Python的C扩展模块。在扩展模块里可以释放GIL。释放GIL期间不应该调用任何Python API。对于一些非常繁重的计算,可以写成C模块,计算前释放GIL,计算后重新申请GIL,并将结果返回给Python。这样就可以让Python进程利用更多CPU资源。每个Python线程都是OS级别的Pthread线程。利用Python管理这些线程比在C层级操作Pthread更方便。

转载地址:http://ntten.baihongyu.com/

你可能感兴趣的文章
linux:Tuning Linux IPv4 route cache
查看>>
Linux内核网络协议栈5-socket端口管理 2
查看>>
Linux内核网络协议栈6-socket监听
查看>>
Linux内核网络协议栈4-socket地址绑定
查看>>
Linux Socket编程(不限Linux)
查看>>
Linux下基于socket多线程并发通信的实现
查看>>
TCP/IP驱动十一 ——内核2.6.26中inet_csk和inet_sk两个函数推导
查看>>
linux listen
查看>>
linux内核网络监听哈希表介绍
查看>>
linux :内核调试神器SystemTap — 简介与使用(一)
查看>>
linux内核:systemtap内核调试 例子
查看>>
linux:cpu 每-CPU 的变量
查看>>
Linux系统调用之SYSCALL_DEFINE
查看>>
linux:如何指定进程运行的CPU
查看>>
linux内核的数据结构:3 每CPU变量
查看>>
linux内核的数据结构:2 散列表
查看>>
linux:socket 系统调用在linux内核中的实现流程图
查看>>
linux:查看内核锁
查看>>
linux内核:CPU私有变量(per-CPU变量)
查看>>
编程之外:使用Latex/Tex创建自己的简历。
查看>>