没有合适的资源?快使用搜索试试~ 我知道了~
Python3标准库之threading进程中管理并发操作方法
0 下载量 113 浏览量
2020-12-20
14:04:57
上传
评论
收藏 257KB PDF 举报
温馨提示
试读
13页
1. threading进程中管理并发操作 threading模块提供了管理多个线程执行的API,允许程序在同一个进程空间并发的运行多个操作。 1.1 Thread对象 要使用Thread,最简单的方法就是用一个目标函数实例化一个Thread对象,并调用start()让它开始工作。 import threading def worker(): """thread worker function""" print('Worker') threads = [] for i in range(5): t = threading.Thread(target=worker) threads
资源推荐
资源详情
资源评论
Python3标准库之标准库之threading进程中管理并发操作方法进程中管理并发操作方法
1. threading进程中管理并发操作进程中管理并发操作
threading模块提供了管理多个线程执行的API,允许程序在同一个进程空间并发的运行多个操作。
1.1 Thread对象对象
要使用Thread,最简单的方法就是用一个目标函数实例化一个Thread对象,并调用start()让它开始工作。
import threading
def worker():
"""thread worker function"""
print('Worker')
threads = [] for i in range(5):
t = threading.Thread(target=worker)
threads.append(t)
t.start()
输出有5行,每一行都是”Worker”。
如果能够创建一个线程,并向它传递参数告诉它要完成什么工作,那么这会很有用。任何类型的对象都可以作为参数传递到线
程。下面的例子传递了一个数,线程将打印出这个数。
import threading
def worker(num):
"""thread worker function"""
print('Worker: %s' % num)
threads = [] for i in range(5):
t = threading.Thread(target=worker, args=(i,))
threads.append(t)
t.start()
现在这个整数参数会包含在各线程打印的消息中。
1.2 确定当前线程确定当前线程
使用参数来标识或命名线程很麻烦,也没有必要。每个Thread实例都有一个带有默认值的名,该默认值可以在创建线程时改
变。如果服务器进程中有多个服务线程处理不同的操作,那么在这样的服务器进程中,对线程命名就很有用。
import threading
import time
def worker():
print(threading.current_thread().getName(), 'Starting')
time.sleep(0.2)
print(threading.current_thread().getName(), 'Exiting')
def my_service():
print(threading.current_thread().getName(), 'Starting')
time.sleep(0.3)
print(threading.current_thread().getName(), 'Exiting')
t = threading.Thread(name='my_service', target=my_service)
w = threading.Thread(name='worker', target=worker)
w2 = threading.Thread(target=worker) # use default name
w.start()
w2.start()
t.start()
调试输出的每一行中包含有当前线程的名。线程名列中有”Thread-1″的行对应未命名的线程w2。
大多数程序并不使用print来进行调试。logging模块支持将线程名嵌入到各个日志消息中(使用格式化代码%(threadName)s)。
通过把线程名包含在日志消息中,就能跟踪这些消息的来源。
import logging
import threading
import time
def worker():
logging.debug('Starting')
time.sleep(0.2)
logging.debug('Exiting')
def my_service():
logging.debug('Starting')
time.sleep(0.3)
logging.debug('Exiting')
logging.basicConfig(
level=logging.DEBUG,
format='[%(levelname)s] (%(threadName)-10s) %(message)s',
)
t = threading.Thread(name='my_service', target=my_service)
w = threading.Thread(name='worker', target=worker)
w2 = threading.Thread(target=worker) # use default name
w.start()
w2.start()
t.start()
而且logging是线程安全的,所以来自不同线程的消息在输出中会有所区分。
1.3 守护与非守护线程守护与非守护线程
到目前为止,示例程序都在隐式地等待所有线程完成工作之后才退出。不过,程序有时会创建一个线程作为守护线程
(daemon),这个线程可以一直运行而不阻塞主程序退出。
如果一个服务不能很容易地中断线程,或者即使让线程工作到一半时中止也不会造成数据损失或破坏(例如,为一个服务监控
工具生成“心跳”的线程),那么对于这些服务,使用守护线程就很有用。要标志一个线程为守护线程,构造线程时便要传
入daemon=True或者要调用它的setDaemon()方法并提供参数True。默认情况下线程不作为守护线程。
import threading
import time
import logging
def daemon():
logging.debug('Starting')
time.sleep(0.2)
logging.debug('Exiting')
def non_daemon():
logging.debug('Starting')
logging.debug('Exiting')
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s',
)
d = threading.Thread(name='daemon', target=daemon, daemon=True)
t = threading.Thread(name='non-daemon', target=non_daemon)
d.start()
t.start()
这个代码的输出中不包含守护线程的“Exiting“消息,因为在从sleep()调用唤醒守护线程之前,所有非守护线程(包括主线程)
已经退出。
要等待一个守护线程完成工作,需要使用join()方法。
import threading
import time
import logging
def daemon():
logging.debug('Starting')
time.sleep(0.2)
logging.debug('Exiting')
def non_daemon():
logging.debug('Starting')
logging.debug('Exiting')
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s',
)
d = threading.Thread(name='daemon', target=daemon, daemon=True)
t = threading.Thread(name='non-daemon', target=non_daemon)
d.start()
t.start()
d.join()
t.join()
使用join()等待守护线程退出意味着它有机会生成它的”Exiting”消息。
默认地,join()会无限阻塞。或者,还可以传入一个浮点值,表示等待线程在多长时间(秒数)后变为不活动。即使线程在这
个时间段内未完成,join()也会返回。
import threading
import time
import logging
def daemon():
logging.debug('Starting')
time.sleep(0.2)
logging.debug('Exiting')
def non_daemon():
logging.debug('Starting')
logging.debug('Exiting')
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s',
)
d = threading.Thread(name='daemon', target=daemon, daemon=True)
t = threading.Thread(name='non-daemon', target=non_daemon)
d.start()
t.start()
d.join(0.1)
print('d.isAlive()', d.isAlive())
t.join()
由于传人的超时时间小于守护线程睡眠的时间,所以join()返回之后这个线程仍是”活着”。
1.4 枚举所有线程枚举所有线程
没有必要为所有守护线程维护一个显示句柄来确保它们在退出主进程之前已经完成。
enumerate()会返回活动 Thread实例的一个列表。这个列表也包括当前线程,由于等待当前线程终止(join)会引入一种死锁情
况,所以必须跳过。
剩余12页未读,继续阅读
资源评论
weixin_38523251
- 粉丝: 3
- 资源: 885
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功