VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > Python基础教程 >
  • Python3标准库:threading进程中管理并发操作(7)

  • else:
  • print(threading.current_thread().name, 'after barrier',
  • worker_id)
  •  
  • NUM_THREADS = 3
  •  
  • barrier = threading.Barrier(NUM_THREADS + 1)
  •  
  • threads = [
  • threading.Thread(
  • name='worker-%s' % i,
  • target=worker,
  • args=(barrier,),
  • )
  • for i in range(NUM_THREADS)
  • ]
  •  
  • for t in threads:
  • print(t.name, 'starting')
  • t.start()
  • time.sleep(0.1)
  •  
  • barrier.abort()
  •  
  • for t in threads:
  • t.join()
  • 这个例子将Barrier配置为多加一个线程,即需要比实际启动的线程再多一个参与线程,所以所有线程中的处理都会阻塞。在被阻塞的各个线程中,abort()调用会产生一个异常。

    1.10 限制资源的并发访问

    有时可能需要允许多个工作线程同时访问一个资源,但要限制总数。例如,连接池支持同时连接,但数目可能是固定的,或者一个网络应用可能支持固定数目的并发下载。这些连接就可以使用Semaphore来管理。

    
    	
    1. import logging
    2. import threading
    3. import time
    4.  
    5. class ActivePool:
    6.  
    7. def __init__(self):
    8. super(ActivePool, self).__init__()
    9. self.active = []
    10. self.lock = threading.Lock()
    11.  
    12. def makeActive(self, name):
    13. with self.lock:
    14. self.active.append(name)
    15. logging.debug('Running: %s', self.active)
    16.  
    17. def makeInactive(self, name):
    18. with self.lock:
    19. self.active.remove(name)
    20. logging.debug('Running: %s', self.active)
    21.  
    22. def worker(s, pool):
    23. logging.debug('Waiting to join the pool')
    24. with s:
    25. name = threading.current_thread().getName()
    26. pool.makeActive(name)
    27. time.sleep(0.1)
    28. pool.makeInactive(name)
    29.  
    30. logging.basicConfig(
    31. level=logging.DEBUG,
    32. format='%(asctime)s (%(threadName)-2s) %(message)s',
    33. )
    34.  
    35. pool = ActivePool()
    36. s = threading.Semaphore(2)
    37. for i in range(4):
    38. t = threading.Thread(
    39. target=worker,
    40. name=str(i),
    41. args=(s, pool),
    42. )
    43. t.start()

    在这个例子中,ActivePool类只作为一种便利方法,用来跟踪某个给定时刻哪些线程能够运行。真正的资源池会为新的活动线程分配一个连接或另外某个值,并且当这个线程工作完成时再回收这个值。在这里,资源池只是用来保存活动线程的名,以显示至少有两个线程在并发运行。

    1.11 线程特定的数据

    有些资源需要锁定以便多个线程使用,另外一些资源则需要保护,以使它们对并非是这些资源的“所有者”的线程隐藏。local()函数会创建一个对象,它能够隐藏值,使其在不同线程中无法被看到。

    
    	
    1. import random
    2. import threading
    3. import logging
    4.  
    5. def show_value(data):
    6. try:
    7. val = data.value
    8. except AttributeError:
    9. logging.debug('No value yet')
    10. else:
    11. logging.debug('value=%s', val)
    12.  
    13. def worker(data):
    14. show_value(data)
    15. data.value = random.randint(1, 100)
    16. show_value(data)
    17.  
    18. logging.basicConfig(
    19. level=logging.DEBUG,
    20. format='(%(threadName)-10s) %(message)s',
    21. )
    22.  
    23. local_data = threading.local()
    24. show_value(local_data)
    25. local_data.value
    
    相关教程