作用:同一个进程空间并发运行多个操作,专业术语简称为:【多线程】

1、任务函数不带参数多线程

#!/usr/bin/env python#-*- coding: utf-8 -*-
importthreadingdefworker():print('worker...')
threads=[]for i in range(3):
task= threading.Thread(target=worker)
threads.append(task)
task.start()print(threads)
threading_simple.py
运行效果
[root@ mnt]# python3 threading_simple.py
worker...
worker...
worker...
[, , ]

2、任务函数带参数多线程

#!/usr/bin/env python#-*- coding: utf-8 -*-
importthreadingdefworker(num):print('worker %s...' %num)
threads=[]for i in range(3):
task= threading.Thread(target=worker, args=(i,))
threads.append(task)
task.start()print(threads)
threading_simple_args.py
运行效果
[root@ mnt]# python3 threading_simple_args.py
worker0...
worker1...
worker2...
[, , ]

3、线程标识名字设置和获取

#!/usr/bin/env python#-*- coding: utf-8 -*-
importthreadingimporttimedefworker():print(threading.current_thread().getName(), 'Starting')
time.sleep(0.2)print(threading.current_thread().getName(), 'Exiting')defmy_service():print(threading.current_thread().getName(), 'Starting')
time.sleep(0.3)print(threading.current_thread().getName(), 'Exiting')
my_service_task= threading.Thread(name='my_service', target=my_service)
worker_task= threading.Thread(name='worker', target=worker)
default_task= threading.Thread(target=worker) #使用默认的名字Thread-1
my_service_task.start()
worker_task.start()
default_task.start()
threading_name.py
运行效果
[root@ mnt]# python3 threading_name.py
my_service Starting
worker Starting
Thread-1Starting
worker Exiting
Thread-1Exiting
my_service Exiting

4、线程标识名字设置和获取,利用logging模块打印出来日志,调试一般不建议用print打印出来

#!/usr/bin/env python#-*- coding: utf-8 -*-
importthreadingimporttimeimportloggingdefworker():
logging.debug('Starting')
time.sleep(0.2)
logging.debug('Exiting')defmy_service():
logging.debug('Starting')
time.sleep(0.3)
logging.debug('Exiting')
logging.basicConfig(
level=logging.DEBUG,#以下格式化,参考官方文档:https://docs.python.org/3/library/logging.html
format='[%(levelname)s] (%(thread)d) (%(threadName)-10s) %(message)s',
)
my_service_task= threading.Thread(name='my_service', target=my_service)
worker_task= threading.Thread(name='worker', target=worker)
default_task= threading.Thread(target=worker) #使用默认的名字Thread-1
my_service_task.start()
worker_task.start()
default_task.start()
threading_name_logging.py
运行效果
[root@ mnt]# python3 threading_name_logging.py
[DEBUG] (140555433457408) (my_service) Starting
[DEBUG] (140555354896128) (worker ) Starting
[DEBUG] (140555346503424) (Thread-1) Starting
[DEBUG] (140555354896128) (worker ) Exiting
[DEBUG] (140555346503424) (Thread-1) Exiting
[DEBUG] (140555433457408) (my_service) Exiting

5、守护线程随着主程序退出而关闭线程

#!/usr/bin/env python#-*- coding: utf-8 -*-
importthreadingimporttimeimportloggingdefdaemon():
logging.debug('daemon Starting...')
time.sleep(0.2)
logging.debug('daemon Exiting...')defnon_daemon():
logging.debug('non_daemon Starting...')
logging.debug('non_daemon Exiting...')
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s')
daemon_task= threading.Thread(name='daemon', target=daemon, daemnotallow=True) #设置为首护线程
non_daemon_task = threading.Thread(name='non_daemon_task', target=non_daemon)
daemon_task.start()
non_daemon_task.start()
threading_daemon.py
运行效果
[root@mnt]#python3 threading_daemon.py
(daemon ) daemon Starting...
(non_daemon_task) non_daemon Starting...

(non_daemon_task) non_daemon Exiting...#由于守护线程还没有执行完,主进程已退出,守护线程即随之被终止,从而导致【daemon Exiting...】没打印出来

6、等待守护线程运行结束,才关闭主程序

#!/usr/bin/env python#-*- coding: utf-8 -*-
importthreadingimporttimeimportloggingdefdaemon():
logging.debug('daemon Starting...')
time.sleep(0.2)
logging.debug('daemon Exiting...')defnon_daemon():
logging.debug('non_daemon Starting...')
logging.debug('non_daemon Exiting...')
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s')
daemon_task= threading.Thread(name='daemon', target=daemon, daemnotallow=True) #设置为首护线程
non_daemon_task = threading.Thread(name='non_daemon_task', target=non_daemon)
daemon_task.start()
non_daemon_task.start()
daemon_task.join()
non_daemon_task.join()
threading_daemon_join
运行效果
[root@ mnt]# python3 threading_daemon_join.py
(daemon ) daemon Starting...
(non_daemon_task) non_daemon Starting...
(non_daemon_task) non_daemon Exiting...
(daemon ) daemon Exiting...
#由于使用的join等待线程运行完成,才结束,所以【daemon Exiting...】可以打印出来

7、设置守护线程的超时时间,防止进入无限阻塞

#!/usr/bin/env python#-*- coding: utf-8 -*-
importthreadingimporttimeimportloggingdefdaemon():
logging.debug('daemon Starting...')
time.sleep(0.2)
logging.debug('daemon Exiting...')defnon_daemon():
logging.debug('non_daemon Starting...')
logging.debug('non_daemon Exiting...')
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s')
daemon_task= threading.Thread(name='daemon', target=daemon, daemnotallow=True) #设置为首护线程
non_daemon_task = threading.Thread(name='non_daemon_task', target=non_daemon)
daemon_task.start()
non_daemon_task.start()
daemon_task.join(0.1) #设置的超时时间0.1秒,因为该任务的函数睡眠0.2s,所以没有运行完成,就已经超时,结束该守护线程
print('isAlive()', daemon_task.isAlive())
non_daemon_task.join()
threading_daemon_join_timeout.py
运行效果
[root@ mnt]# python3 threading_daemon_join_timeout.py
(daemon ) daemon Starting...
(non_daemon_task) non_daemon Starting...
(non_daemon_task) non_daemon Exiting...
isAlive() True #这里是判断线程是否在运行,True表在线程还在运行

8、利用threading.enumerate()枚举的方法,设置守护线程等待运行完成

#!/usr/bin/env python#-*- coding: utf-8 -*-
importthreadingimporttimeimportloggingimportrandomdefworker():
pause= random.randint(1, 5) / 10logging.debug('睡眠 %0.2f 秒', pause)
time.sleep(pause)
logging.debug('worker 结束')
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s')for i in range(3):
task= threading.Thread(target=worker, daemnotallow=True)
task.start()
main_thread=threading.main_thread()for task_obj in threading.enumerate(): #threading.enumerate():返回当前运行守护线程的实例
if task_obj ismain_thread:continuelogging.debug('等待 %s', task_obj.getName())
task_obj.join()
threading_enumerate.py
运行效果
[root@ mnt]# python3 threading_enumerate.py
(Thread-1 ) 睡眠 0.30秒
(Thread-2 ) 睡眠 0.10秒
(Thread-3 ) 睡眠 0.10秒
(MainThread) 等待 Thread-1(Thread-2) worker 结束
(Thread-3) worker 结束
(Thread-1) worker 结束
(MainThread) 等待 Thread-2(MainThread) 等待 Thread-3

9、利用继承threading.Thread类,实现无参的多线程

#!/usr/bin/env python#-*- coding: utf-8 -*-
importthreadingimportloggingclassMyThread(threading.Thread):defrun(self):
logging.debug('运行...')
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s',
)for i in range(5):
task=MyThread()
task.start()
threading_subclass.py
运行效果
[root@ mnt]#
[root@python-mysql mnt]# python3 threading_subclass.py
(Thread-1) 运行...
(Thread-2) 运行...
(Thread-3) 运行...
(Thread-4) 运行...
(Thread-5 ) 运行...

10、利用继承threading.Thread类,实现有参的多线程

#!/usr/bin/env python#-*- coding: utf-8 -*-
importthreadingimportloggingclassMyThread(threading.Thread):def __init__(self, group=None, target=None, name=None, daemnotallow=None, args=(), kwargs=None):
super(MyThread, self).__init__(group=group, target=target, name=name, daemnotallow=daemon)
self.args=args
self.kwargs=kwargsdefrun(self):
logging.debug('运行...args : %s,kwargs : %s', self.args, self.kwargs)
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s',
)for i in range(5):
task= MyThread(args=(i,), kwargs={'a': 'A', 'b': 'B'})
task.start()
threading_subclass_args.py
运行效果
[root@ mnt]# python3 threading_subclass_args.py
(Thread-1 ) 运行...args : (0,),kwargs : {'a': 'A', 'b': 'B'}
(Thread-2 ) 运行...args : (1,),kwargs : {'a': 'A', 'b': 'B'}
(Thread-3 ) 运行...args : (2,),kwargs : {'a': 'A', 'b': 'B'}
(Thread-4 ) 运行...args : (3,),kwargs : {'a': 'A', 'b': 'B'}
(Thread-5 ) 运行...args : (4,),kwargs : {'a': 'A', 'b': 'B'}

11、定时器线程threading.Timer

#!/usr/bin/env python#-*- coding: utf-8 -*-
importthreadingimportloggingimporttimedefdelayed():
logging.debug('delayed运行...')
logging.basicConfig(
level=logging.DEBUG,
format="(%(threadName)-10s) %(message)s")
task_1= threading.Timer(0.3, delayed)
task_1.setName('task_1')
task_2= threading.Timer(0.3, delayed)
task_2.setName('task_2')
logging.debug('开始运行Timer')
task_1.start()
task_2.start()
logging.debug('取消前等待')
time.sleep(0.2)
logging.debug('取消 %s' %task_2.getName())
task_2.cancel()
logging.debug('取消完成')
threading_timer.py
运行效果
[root@ mnt]# python3 threading_timer.py
(MainThread) 开始运行Timer
(MainThread) 取消前等待
(MainThread) 取消 task_2
(MainThread) 取消完成
(task_1 ) delayed运行...
#task_2已经被取消,所以没有运行

12、线程间信号相互传送threading.Event

#!/usr/bin/env python#-*- coding: utf-8 -*-
importthreadingimportloggingimporttimedefwait_for_event(event_obj):
logging.debug('等待事件的开始')
event_is_set=event_obj.wait()
logging.debug('事件设置 %s' %event_is_set)defwait_for_event_timeout(event_obj, timeout):while notevent_obj.is_set():
logging.debug('等待事件超时开始')
event_is_set=event_obj.wait(timeout)ifevent_is_set:
logging.debug('处理事件')else:
logging.debug('做其他工作')
logging.basicConfig(
level=logging.DEBUG,
format="(%(threadName)-10s) %(message)s")
event_obj=threading.Event()
task_1=threading.Thread(
name='block',
target=wait_for_event,
args=(event_obj,)
)
task_1.start()
task_2=threading.Thread(
name='nonblock',
target=wait_for_event_timeout,
args=(event_obj, 2)
)
task_2.start()
logging.debug('在呼叫前等待 Event.set()')
time.sleep(0.3)
event_obj.set()
logging.debug('事件已经设置')
threading_event.py
运行效果
[root@ mnt]# python3 threading_event.py
(block ) 等待事件的开始
(nonblock ) 等待事件超时开始
(MainThread) 在呼叫前等待 Event.set()
(MainThread) 事件已经设置
(block ) 事件设置 True
(nonblock ) 处理事件

13、控制资源访问_计数器_多线程加阻塞锁的示例

#!/usr/bin/env python#-*- coding: utf-8 -*-
importthreadingimportloggingimporttimeimportrandomclassCounter(object):def __init__(self, start=0):
self.lock=threading.Lock()
self.value=startdefincrement(self):
logging.debug('等待锁')
self.lock.acquire()try:
logging.debug('获取锁')
self.value+= 1
finally:
self.lock.release()defworker(c):for i in range(2):
pause=random.random()
logging.debug('睡眠 %0.02f', pause)
time.sleep(pause)
c.increment()
logging.debug('worker运行结束')
logging.basicConfig(
level=logging.DEBUG,
format="(%(threadName)-10s) %(message)s")
counter=Counter()for i in range(2):
t= threading.Thread(target=worker, args=(counter,))
t.start()
logging.debug('等待线程worker运行结束')
main_thread=threading.main_thread()for t inthreading.enumerate():if t is notmain_thread:
t.join()
logging.debug('Counter: %d', counter.value)
threading_lock.py
运行效果
[root@mnt]# python3 threading_lock.py
(Thread-1 ) 睡眠 0.36(Thread-2 ) 睡眠 0.77(MainThread) 等待线程worker运行结束
(Thread-1) 等待锁
(Thread-1) 获取锁
(Thread-1 ) 睡眠 0.43(Thread-2) 等待锁
(Thread-2) 获取锁
(Thread-2 ) 睡眠 0.12(Thread-1) 等待锁
(Thread-1) 获取锁
(Thread-1) worker运行结束
(Thread-2) 等待锁
(Thread-2) 获取锁
(Thread-2) worker运行结束
(MainThread) Counter:4 #运行4次,所以显示4

14、控制资源访问_计数器_多线程非阻塞锁的示例

#!/usr/bin/env python#-*- coding: utf-8 -*-
importthreadingimportloggingimporttimedeflock_holder(lock_obj):
logging.debug('lock_holder 开始')whileTrue:
lock_obj.acquire()try:
logging.debug('Holding')
time.sleep(0.5)finally:
logging.debug('Not Holding')
lock_obj.release()
time.sleep(0.5)defworker(lock_obj):
logging.debug('worker 开始')
num_tries=0
num_acquires=0while num_acquires < 3:
time.sleep(0.5)
logging.debug('尝试获取锁')
have_it= lock_obj.acquire(0) #主要核心代码在这里,不断尝试获取锁,通过这个判断锁是否释放可以获取
try:
num_tries+= 1
ifhave_it:
logging.debug('重试次数 %d: 得到锁', num_tries)
num_acquires+= 1
else:
logging.debug('重试次数 %d: 没有得到锁', num_tries)finally:ifhave_it:
lock_obj.release()
logging.debug('获取锁一共尝试的 %d 次', num_tries)
logging.basicConfig(
level=logging.DEBUG,
format="(%(threadName)-10s) %(message)s")
lock=threading.Lock()
holder=threading.Thread(
target=lock_holder,
args=(lock,),
name='LockHolder',
daemnotallow=True,
)
holder.start()
worker=threading.Thread(
target=worker,
args=(lock,),
name='Worker',
)
worker.start()
threading_lock_nonblock.py
运行结果
[root@ mnt]# python3 threading_lock_nonblock.py
(LockHolder) lock_holder 开始
(LockHolder) Holding
(Worker ) worker 开始
(LockHolder) Not Holding
(Worker ) 尝试获取锁
(Worker ) 重试次数1: 得到锁
(LockHolder) Holding
(Worker ) 尝试获取锁
(Worker ) 重试次数2: 没有得到锁
(LockHolder) Not Holding
(Worker ) 尝试获取锁
(Worker ) 重试次数3: 得到锁
(LockHolder) Holding
(Worker ) 尝试获取锁
(Worker ) 重试次数4: 没有得到锁
(LockHolder) Not Holding
(Worker ) 尝试获取锁
(Worker ) 重试次数5: 得到锁
(Worker ) 获取锁一共尝试的5次
#尝试的次数是随机,这样子的好处,不会因为阻塞占有CPU资源

15、互斥锁

#!/usr/bin/env python#-*- coding: utf-8 -*-
importthreading
lock=threading.Lock()print('第一个锁', lock.acquire())print('第二个锁', lock.acquire(0))
threading_lock_reacquire.py
运行效果
[root@ mnt]#python3 threading_lock_reacquire.py
第一个锁 True
第二个锁 False

16、同步锁

importthreading
lock=threading.RLock()print('第一个锁', lock.acquire())print('第二个锁', lock.acquire(0))
threading_rlock.py
运行效果
[root@ mnt]# python3 threading_rlock.py
第一个锁 True
第二个锁 True

17、利用with管理锁,无需每次都释放锁lock.release()

#!/usr/bin/env python#-*- coding: utf-8 -*-
importthreadingimportloggingdefworker_with(lock):
with lock:
logging.debug('当前运行是用with 获取锁')defworker_no_with(lock):
lock.acquire()try:
logging.debug('当前运行是用 lock.acquire() 获取锁')finally:
lock.release()
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s',
)
lock=threading.Lock()
with_open_lock= threading.Thread(target=worker_with, args=(lock,))
no_with_open_lock= threading.Thread(target=worker_no_with, args=(lock,))
with_open_lock.start()
no_with_open_lock.start()
threading_lock_with.py
运行效果
[root@ mnt]# python3 threading_with_lock.py
(Thread-1) 当前运行是用with 获取锁
(Thread-2 ) 当前运行是用 lock.acquire() 获取锁

18、利用threading.Condition(),实现线程同步,下面是生产者和消费者的示例

#!/usr/bin/env python#-*- coding: utf-8 -*-
importthreadingimportloggingimporttimedefconsumer(condition_obj):"""消费者"""logging.debug('消费者线程开启')
with condition_obj:
condition_obj.wait()
logging.debug('资源可供消费者使用。')defproducer(condition_obj):"""生产者"""logging.debug('生产者线程开启')
with condition_obj:
logging.debug('生产可用资源')
condition_obj.notifyAll()
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s',
)
condition_obj=threading.Condition()#消费者实例1
c1 =threading.Thread(
name='c1',
target=consumer,
args=(condition_obj,)
)#消费者实例1
c2 =threading.Thread(
name='c2',
target=consumer,
args=(condition_obj,)
)#生产者实例
p =threading.Thread(
name='p',
target=producer,
args=(condition_obj,)
)
c1.start()
time.sleep(0.2)
c2.start()
time.sleep(0.2)
p.start()
threading_condition.py
运行效果
[root@ mnt]# python3 threading_condition.py
(c1 ) 消费者线程开启
(c2 ) 消费者线程开启
(p ) 生产者线程开启
(p ) 生产可用资源
(c1 ) 资源可供消费者使用。
(c2 ) 资源可供消费者使用。

19、线程同步threading.Barrier() ,作用:等待所有线程一起开启后,再全部一起执行主要的功能

#!/usr/bin/env python#-*- coding: utf-8 -*-
importthreadingimportloggingimporttimedefworker(barrier):
logging.debug('当前线程名字: %s 与 %s 其他人一起等待后面的功能' %(threading.current_thread().name, barrier.n_waiting))
worker_id=barrier.wait()
logging.debug('%s 已经等待完毕 %s' %(threading.current_thread().name, worker_id))
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s',
)
NUM_THREADS= 3barrier=threading.Barrier(NUM_THREADS)
threads=[
threading.Thread(
name='worker-%s' %i,
target=worker,
args=(barrier,)
)for i inrange(NUM_THREADS)
]#这里是实例化3个线程,[, , ]
for thread_obj inthreads:
logging.debug('%s 开启' %thread_obj.name)
thread_obj.start()
time.sleep(0.2)for thread_obj inthreads:
thread_obj.join()
threading_barrier.py
运行效果
[root@ mnt]# python3 threading_barrier.py
(MainThread) worker-0开启
(worker-0 ) 当前线程名字: worker-0 与 0其他人一起等待后面的功能
(MainThread) worker-1开启
(worker-1 ) 当前线程名字: worker-1 与 1其他人一起等待后面的功能
(MainThread) worker-2开启
(worker-2 ) 当前线程名字: worker-2 与 2其他人一起等待后面的功能
(worker-2 ) worker-2 已经等待完毕 2(worker-0 ) worker-0 已经等待完毕 0(worker-1 ) worker-1 已经等待完毕 1

20、线程同步barrier.abort()中断的操作,作用:等待所有线程运行后面的功能,然后对它进行中断的操作,使用停止运行

#!/usr/bin/env python#-*- coding: utf-8 -*-
importthreadingimportloggingimporttimedefworker(barrier):
logging.debug('当前线程名字: %s 与 %s 其他人一起等待后面的功能' %(threading.current_thread().name, barrier.n_waiting))try:
worker_id=barrier.wait()exceptthreading.BrokenBarrierError:
logging.debug('%s 中断', threading.current_thread().name)else:
logging.debug('%s 已经等待完毕 %s' %(threading.current_thread().name, worker_id))
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s',
)
NUM_THREADS= 3
#barrier.abort()必须多加一个线程,所以这里需要加1
barrier = threading.Barrier(NUM_THREADS + 1)
threads=[
threading.Thread(
name='worker-%s' %i,
target=worker,
args=(barrier,)
)for i inrange(NUM_THREADS)
]#这里是实例化3个线程,[, , ]
for thread_obj inthreads:
logging.debug('%s 开启' %thread_obj.name)
thread_obj.start()
time.sleep(0.1)#中断线程一起同步运行
barrier.abort()for thread_obj inthreads:
thread_obj.join()
threading_barrier_abort.py
运行效果
[root@ mnt]# python3 threading_barrier_abort.py
(MainThread) worker-0开启
(worker-0 ) 当前线程名字: worker-0 与 0其他人一起等待后面的功能
(MainThread) worker-1开启
(worker-1 ) 当前线程名字: worker-1 与 1其他人一起等待后面的功能
(MainThread) worker-2开启
(worker-2 ) 当前线程名字: worker-2 与 2其他人一起等待后面的功能
(worker-0 ) worker-0中断
(worker-1 ) worker-1中断
(worker-2 ) worker-2 中断

21、threading.Semaphore(),自定义线程池

#!/usr/bin/env python#-*- coding: utf-8 -*-
importthreadingimportloggingimporttimeclassActivePool(object):"""活动池"""
def __init__(self):
self.active=[]
self.lock=threading.Lock()defmakeActive(self, name):"""获取一个锁,把活动的名字增加于列表中"""with self.lock:
self.active.append(name)
logging.debug('运行:%s' %self.active)defmakeInactive(self, name):
with self.lock:
self.active.remove(name)
logging.debug('运行:%s', self.active)defworker(semaphore_obj, pool):
logging.debug('正在等待加入池')
with semaphore_obj:
name=threading.current_thread().getName()
pool.makeActive(name)
time.sleep(0.1)
pool.makeInactive(name)
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s (%(threadName)-10s) %(message)s',
)
pool=ActivePool()
semaphore_obj= threading.Semaphore(2)for i in range(4):
t=threading.Thread(
target=worker,
name=str(i),
args=(semaphore_obj, pool)
)
t.start()
threading_semaphore.py
运行效果
[root@ mnt]# python3 threading_semaphore.py2019-12-08 15:31:47,387 (0) 正在等待加入池2019-12-08 15:31:47,387 (0 ) 运行:['0']2019-12-08 15:31:47,388 (1) 正在等待加入池2019-12-08 15:31:47,389 (1 ) 运行:['0', '1']2019-12-08 15:31:47,389 (2) 正在等待加入池2019-12-08 15:31:47,390 (3) 正在等待加入池2019-12-08 15:31:47,489 (0 ) 运行:['1']2019-12-08 15:31:47,491 (1) 运行:[]2019-12-08 15:31:47,492 (2 ) 运行:['2']2019-12-08 15:31:47,494 (3 ) 运行:['2', '3']2019-12-08 15:31:47,593 (2 ) 运行:['3']2019-12-08 15:31:47,596 (3 ) 运行:[]

22、threading.local(),本地线程任务运行隔离

#!/usr/bin/env python#-*- coding: utf-8 -*-
importrandomimportthreadingimportloggingdefshow_value(local_obj):try:
val=local_obj.valueexceptAttributeError:
logging.debug('值不存在')else:
logging.debug('value=%s', val)defworker(local_obj):
show_value(local_obj)
local_obj.value= random.randint(1, 100)
show_value(local_obj)
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s (%(threadName)-10s) %(message)s',
)
local_obj=threading.local()#第一次运行没有设置value值,会报AttributeError异常
show_value(local_obj)#第二次运行有设置value值,所以会显示出值
local_obj.value = 1000show_value(local_obj)for i in range(2):
t=threading.Thread(
target=worker,
args=(local_obj,),
)
t.start()
threading_local.py
运行效果
[root@ mnt]# python3 threading_local.py2019-12-08 16:23:17,696(MainThread) 值不存在2019-12-08 16:23:17,697 (MainThread) value=1000
2019-12-08 16:23:17,697 (Thread-1) 值不存在2019-12-08 16:23:17,698 (Thread-1 ) value=26
2019-12-08 16:23:17,698 (Thread-2) 值不存在2019-12-08 16:23:17,698 (Thread-2 ) value=39

23、threading.local(),本地线程任务运行隔离,初始化全局变量值

#!/usr/bin/env python#-*- coding: utf-8 -*-
importrandomimportthreadingimportloggingdefshow_value(local_obj):try:
val=local_obj.valueexceptAttributeError:
logging.debug('值不存在')else:
logging.debug('value=%s', val)defworker(local_obj):
show_value(local_obj)
local_obj.value= random.randint(1, 100)
show_value(local_obj)
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s (%(threadName)-10s) %(message)s',
)classMyLocal(threading.local):def __init__(self, value, *args, **kwargs):
super(MyLocal, self).__init__(*args, **kwargs)
logging.debug('初始化值 %r', self)
self.value=value
local_obj= MyLocal(1000)
show_value(local_obj)for i in range(2):
t=threading.Thread(
target=worker,
args=(local_obj,)
)
t.start()
threading_local.default.py
测试效果
[root@ mnt]# python3 threading_local.default.py2019-12-08 16:28:48,168 (MainThread) 初始化值 <__main__.MyLocal object at 0x7fe58b6e1408>
2019-12-08 16:28:48,168 (MainThread) value=1000
2019-12-08 16:28:48,169 (Thread-1 ) 初始化值 <__main__.MyLocal object at 0x7fe58b6e1408>
2019-12-08 16:28:48,169 (Thread-1 ) value=1000
2019-12-08 16:28:48,169 (Thread-1 ) value=11
2019-12-08 16:28:48,170 (Thread-2 ) 初始化值 <__main__.MyLocal object at 0x7fe58b6e1408>
2019-12-08 16:28:48,170 (Thread-2 ) value=1000
2019-12-08 16:28:48,170 (Thread-2 ) value=7