赞
踩
并发:假同时,一段时间内同时处理多个任务
并行:真同时,同时处理多个任务,必须多核,是并发的子集
threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)
线程
import threading
def worker():
print('work')
thread = threading.Thread(target=worker) # 创建线程对象,target参数是一个函数,这个函数即线程要执行的逻辑
thread.start() # start函数启动一个线程,当这个线程的逻辑执行,设计自动退出,自己退出。
import time
def worker(num):
time.sleep(1)
print('worker-{}'.format(num))
for z in range(5):
t = threading.Thread(target=worker, args=(z, )) # 元组参数列表
t.start()
如何标识一个线程
threading.current_thread() # 返回当前线程
<<<_MainThread(MainThread, started 140428986173248)>
thread = threading.current_thread()
thread.name # 线程名,可重名
<<'MainThread'
thread.ident # 线程id
<<140428986173248
logging
import logging
logging.warning('haha')
<
import importlib
importlib.reload(logging) # 重新引入,覆盖缓存
# import导入一次会在缓存中固定,,reload会从标准库中导入
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(threadName)s %(message)s') # 配置logging
logging.warning('haha') # 替代print
<<2017-03-11 09:42:47,814 WARNING [MainThread haha]
参数
# 通过args参数传递位置参数,通过kwargs传递关键字参数
def add(x, y):
logging.info(x + y)
add(1, 2)
add(x=1, y=2)
threading.Thread(target=add, args=(1, 2)).start()
threading.Thread(target=add, kwargs={'x':1, 'y':2}).start()
threading.Thread(target=add, args=(1,), kwargs={'y':2}).start()
<<2017-03-11 09:45:23,651 INFO [Thread-18 3]
线程名
threading.Thread(target=add, args=(1, 2), name='adc').start()
2017-03-11 09:47:55,442 INFO [adc 3]
# 通过name参数设置线程名字,日志可以带线程名
# 线程可以重名,唯一标识符是id,但是通常应该避免线程重名。通常线程名命名加前缀
线程通信的必要
importlib.reload(logging)
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s [%(threadName)s %(message)s]')
def ww(num):
logging.info('ww-{}--'.format(num))
time.sleep(1)
logging.info('ww-{}'.format(num))
for i in range(5):
t = threading.Thread(target=ww, args=(i, ), name='ww1')
t.start()
for i in range(5):
t = threading.Thread(target=ww, args=(i, ), name='ww2')
t.start()
<<2017-03-11 10:24:58,067 INFO [ww1 ww-0--]
<<2017-03-11 10:24:58,071 INFO [ww1 ww-1--]
<<2017-03-11 10:24:58,074 INFO [ww1 ww-2--]
<<2017-03-11 10:24:58,076 INFO [ww1 ww-3--]
<<2017-03-11 10:24:58,078 INFO [ww1 ww-4--]
<<2017-03-11 10:24:58,081 INFO [ww2 ww-0--]
<<2017-03-11 10:24:58,084 INFO [ww2 ww-1--]
<<2017-03-11 10:24:58,086 INFO [ww2 ww-2--]
<<2017-03-11 10:24:58,105 INFO [ww2 ww-3--]
<<2017-03-11 10:24:58,121 INFO [ww2 ww-4--]
<<2017-03-11 10:24:59,073 INFO [ww1 ww-0]
<<2017-03-11 10:24:59,074 INFO [ww1 ww-1]
<<2017-03-11 10:24:59,077 INFO [ww1 ww-2]
<<2017-03-11 10:24:59,080 INFO [ww1 ww-3]
<<2017-03-11 10:24:59,082 INFO [ww1 ww-4]
<<2017-03-11 10:24:59,086 INFO [ww2 ww-0]
<<2017-03-11 10:24:59,087 INFO [ww2 ww-1]
<<2017-03-11 10:24:59,106 INFO [ww2 ww-2]
<<2017-03-11 10:24:59,122 INFO [ww2 ww-3]
<<2017-03-11 10:24:59,130 INFO [ww2 ww-4]
# 多线程自动并发,各线程调度顺序需要进程间通信来控制
daemon
# 在pycharm中
import time
import logging
import threading
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s [%(threadName)s %(message)s]')
def worker1():
logging.info('starting')
time.sleep(20)
logging.info('completed')
def worker2():
logging.info('starting')
time.sleep(3)
logging.info('completed')
if __name__ == '__main__':
logging.info('start1')
t = threading.Thread(target=worker1, name='non-daemon')
t.start()
t = threading.Thread(target=worker2, daemon=True, name='daemon')
t.start()
logging.info('stop1')
<<2017-03-11 11:30:08,007 INFO [MainThread start1]
<<2017-03-11 11:30:08,026 INFO [non-daemon starting]
<<2017-03-11 11:30:08,044 INFO [daemon starting]
<<2017-03-11 11:30:08,045 INFO [MainThread stop1]
<<2017-03-11 11:30:11,048 INFO [daemon completed]
<<2017-03-11 11:30:28,040 INFO [non-daemon completed]
# daemon参数默认False
# daemon标记的子线程会随父线程退出而退出,可能执行完,可能未执行完
# none-daemon标记的子线程,主线程会等待其执行完再退出
依靠时间片解述:
join
# join方法会阻塞,直到线程退出或者超时,timeout 是可选的,如果不设置timeout,会一直等待线程退出。不占用CPU时间
# 可用来强制等待deamon线程执行完成
t.join()
# 默认等待退出
t.join(timeout)
# 等待超时
thread local
del(thread) # 删除对象
ctz = threading.local()
ctz.data = 5
data = 'abc'
def worker():
logging.info(data)
logging.info(ctz.data)
worker()
<<2017-03-11 11:19:16,158 INFO [MainThread abc]
<<2017-03-11 11:19:16,173 INFO [MainThread 5]
threading.Thread(target=worker).start()
<<2017-03-11 11:21:12,623 INFO [Thread-23 abc]
# threading.local()增加的属性只存在当前线程,只对当前线程可见
定时器/延迟执行
def worker():
logging.info('run')
t = threading.Timer(interval=5, function=worker) # 用function不是target
t.start() # 停顿5秒 执行,没有name
t.name
<<'Thread-28'
<<2017-03-11 11:37:50,080 INFO [Thread-28 run]
t.name = 'worker' # 这样设置name
t.start()
t.cancel()
# 取消执行,线程结束。 在start后,在interval内,之间存在
threading.enumerate() # 查看当前所有线程
def worker():
logging.info('starting')
time.sleep(30)
logging.info('completed')
t = threading.Timer(interval=0, function=worker)
t.start()
<<2017-03-11 11:45:50,224 INFO [Thread-32 starting]
t.cancel()
t.is_alive()
<
<<2017-03-11 11:46:20,248 INFO [Thread-32 completed]
# 当function参数指定函数开始执行的时候,cancel无效,无法取消
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。