Python之threading模块的使用

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

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

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import threading

def worker():
    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...
[<Thread(Thread-1, stopped 140040860006144)>, <Thread(Thread-2, stopped 140040860006144)>, <Thread(Thread-3, stopped 140040860006144)>]

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

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import threading

def worker(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 
worker 0...
worker 1...
worker 2...
[<Thread(Thread-1, stopped 140326829315840)>, <Thread(Thread-2, stopped 140326829315840)>, <Thread(Thread-3, stopped 140326829315840)>]

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

#!/usr/bin/env python
# -*- coding: utf-8 -*-

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')

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-1 Starting
worker Exiting
Thread-1 Exiting
my_service Exiting

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

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import threading
import time
import logging

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,
    # 以下格式化,参考官方文档: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 -*-

import threading
import time
import logging

def daemon():
    logging.debug('daemon Starting...')
    time.sleep(0.2)
    logging.debug('daemon Exiting...')


def non_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, daemon=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 -*-

import threading
import time
import logging

def daemon():
    logging.debug('daemon Starting...')
    time.sleep(0.2)
    logging.debug('daemon Exiting...')

def non_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, daemon=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 -*-

import threading
import time
import logging

def daemon():
    logging.debug('daemon Starting...')
    time.sleep(0.2)
    logging.debug('daemon Exiting...')


def non_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, daemon=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 -*-

import threading
import time
import logging
import random

def worker():
    pause = random.randint(1, 5) / 10
    logging.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, daemon=True)
    task.start()

main_thread = threading.main_thread()
for task_obj in threading.enumerate(): #threading.enumerate():返回当前运行守护线程的实例
    if task_obj is main_thread:
        continue
    logging.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 -*-

import threading
import logging

class MyThread(threading.Thread):
    def run(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 -*-

import threading
import logging

class MyThread(threading.Thread):
    def __init__(self, group=None, target=None, name=None, daemon=None, args=(), kwargs=None):
        super(MyThread, self).__init__(group=group, target=target, name=name, daemon=daemon)
        self.args = args
        self.kwargs = kwargs

    def run(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 -*-

import threading
import logging
import time

def delayed():
    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 -*-

import threading
import logging
import time

def wait_for_event(event_obj):
    logging.debug('等待事件的开始')
    event_is_set = event_obj.wait()
    logging.debug('事件设置 %s' % event_is_set)

def wait_for_event_timeout(event_obj, timeout):
    while not event_obj.is_set():
        logging.debug('等待事件超时开始')
        event_is_set = event_obj.wait(timeout)
        if event_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 -*-

import threading
import logging
import time
import random

class Counter(object):
    def __init__(self, start=0):
        self.lock = threading.Lock()
        self.value = start

    def increment(self):
        logging.debug('等待锁')
        self.lock.acquire()
        try:
            logging.debug('获取锁')
            self.value += 1
        finally:
            self.lock.release()

def worker(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 in threading.enumerate():
    if t is not main_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 -*-

import threading
import logging
import time

def lock_holder(lock_obj):
    logging.debug('lock_holder 开始')
    while True:
        lock_obj.acquire()
        try:
            logging.debug('Holding')
            time.sleep(0.5)
        finally:
            logging.debug('Not Holding')
            lock_obj.release()
        time.sleep(0.5)

def worker(lock_obj):
    logging.debug('worker 开始')
    num_tries = 0
    num_acquires = 0
    while num_acquires < 3:
        time.sleep(0.5)
        logging.debug('尝试获取锁')
        have_it = lock_obj.acquire(0)  # 主要核心代码在这里,不断尝试获取锁,通过这个判断锁是否释放可以获取
        try:
            num_tries += 1
            if have_it:
                logging.debug('重试次数 %d: 得到锁', num_tries)
                num_acquires += 1
            else:
                logging.debug('重试次数 %d: 没有得到锁', num_tries)
        finally:
            if have_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',
    daemon=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 -*-
import threading

lock = threading.Lock()

print('第一个锁', lock.acquire())
print('第二个锁', lock.acquire(0))
threading_lock_reacquire.py

运行效果

[root@ mnt]# python3 threading_lock_reacquire.py
第一个锁 True
第二个锁 False

16、同步锁

import threading

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 -*-

import threading
import logging

def worker_with(lock):
    with lock:
        logging.debug('当前运行是用with 获取锁')

def worker_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 -*-

import threading
import logging
import time

def consumer(condition_obj):
    """消费者"""
    logging.debug('消费者线程开启')
    with condition_obj:
        condition_obj.wait()
        logging.debug('资源可供消费者使用。')

def producer(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 -*-

import threading
import logging
import time

def worker(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 = 3

barrier = threading.Barrier(NUM_THREADS)

threads = [
    threading.Thread(
        name='worker-%s' % i,
        target=worker,
        args=(barrier,)
    ) for i in range(NUM_THREADS)
]  # 这里是实例化3个线程,[<Thread(worker-0, initial)>, <Thread(worker-1, initial)>, <Thread(worker-2, initial)>]

for thread_obj in threads:
    logging.debug('%s 开启' % thread_obj.name)
    thread_obj.start()
    time.sleep(0.2)

for thread_obj in threads:
    thread_obj.join()
threading_barrier.py

运行效果

[root@ mnt]# python3 threading_barrier.py 
(MainThread) worker-0 开启
(worker-0  ) 当前线程名字: worker-00 其他人一起等待后面的功能
(MainThread) worker-1 开启
(worker-1  ) 当前线程名字: worker-11 其他人一起等待后面的功能
(MainThread) worker-2 开启
(worker-2  ) 当前线程名字: worker-22 其他人一起等待后面的功能
(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 -*-

import threading
import logging
import time

def worker(barrier):
    logging.debug('当前线程名字: %s 与 %s 其他人一起等待后面的功能' % (threading.current_thread().name, barrier.n_waiting))
    try:
        worker_id = barrier.wait()
    except threading.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 in range(NUM_THREADS)
]  # 这里是实例化3个线程,[<Thread(worker-0, initial)>, <Thread(worker-1, initial)>, <Thread(worker-2, initial)>]

for thread_obj in threads:
    logging.debug('%s 开启' % thread_obj.name)
    thread_obj.start()
    time.sleep(0.1)

#中断线程一起同步运行
barrier.abort()

for thread_obj in threads:
    thread_obj.join()
threading_barrier_abort.py

运行效果

[root@ mnt]# python3 threading_barrier_abort.py 
(MainThread) worker-0 开启
(worker-0  ) 当前线程名字: worker-00 其他人一起等待后面的功能
(MainThread) worker-1 开启
(worker-1  ) 当前线程名字: worker-11 其他人一起等待后面的功能
(MainThread) worker-2 开启
(worker-2  ) 当前线程名字: worker-22 其他人一起等待后面的功能
(worker-0  ) worker-0 中断
(worker-1  ) worker-1 中断
(worker-2  ) worker-2 中断

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

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import threading
import logging
import time

class ActivePool(object):
    """活动池"""

    def __init__(self):
        self.active = []
        self.lock = threading.Lock()

    def makeActive(self, name):
        """获取一个锁,把活动的名字增加于列表中"""
        with self.lock:
            self.active.append(name)
            logging.debug('运行:%s' % self.active)

    def makeInactive(self, name):
        with self.lock:
            self.active.remove(name)
            logging.debug('运行:%s', self.active)


def worker(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.py 
2019-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 -*-

import random
import threading
import logging

def show_value(local_obj):
    try:
        val = local_obj.value
    except AttributeError:
        logging.debug('值不存在')
    else:
        logging.debug('value=%s', val)

def worker(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 = 1000
show_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.py
2019-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 -*-

import random
import threading
import logging

def show_value(local_obj):
    try:
        val = local_obj.value
    except AttributeError:
        logging.debug('值不存在')
    else:
        logging.debug('value=%s', val)

def worker(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',
)

class MyLocal(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.py 
2019-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
posted @ 2019-12-08 16:30  小粉优化大师  阅读(3459)  评论(0编辑  收藏  举报