【问题标题】:Threads with decorators带有装饰器的线程
【发布时间】:2012-12-23 11:03:18
【问题描述】:

我正在尝试在我的应用程序中实现线程(使用装饰器),但无法理解关于锁和管理线程的一些事情。

import threading

def run_in_thread(fn):
    def run(*k, **kw):
        t = threading.Thread(target=fn, args=k, kwargs=kw)
        t.start()
    return run

class A:
    @run_in_thread
    def method1(self):
        for x in range(10000):
            print x


    @run_in_thread
    def method2(self):
        for y in list('wlkefjwfejwiefwhfwfkjshkjadgfjhkewgfjwjefjwe'):
            print y

    def stop_thread(self):
        pass

c = A()
c.method1()
c.method2()
  1. 据我了解,method1 和 method2 不是同步的,而是在锁的帮助下实现的那些东西的同步。如何为我的装饰器功能添加锁?

  2. 如何实现使用装饰器停止长线程的方法?

【问题讨论】:

  • 你想在两个线程之间同步什么?
  • 可能我说的有些不对。我希望在某些情况下(并非总是)有可能在 1 个线程之后运行第二个线程,而不是并行。
  • 当然,最简单的方法是在这种情况下不在线程中运行代码。在这种情况下,您可以有两种类似的方法,一种在线程中执行任务,另一种不执行。或者在调用时传入一个参数,指示调用是否要线程化。

标签: python multithreading decorator


【解决方案1】:

如果你把函数扩展到

def run_in_thread(fn):
    def run(*k, **kw):
        t = threading.Thread(target=fn, args=k, kwargs=kw)
        t.start()
        return t # <-- this is new!
    return run

我。 e.,让包装函数返回创建的线程,你可以这样做

c = A()
t1 = c.method1()
t1.join() # wait for it to finish
t2 = c.method2()
# ...

我。 e,获取原始方法所在的线程,对它做任何你想做的事情(例如加入它),然后才调用下一个方法。

如果您在给定的情况下不需要它,您可以随意省略它。

【讨论】:

  • 你能在这里解释一下这段代码发生了什么吗?
  • @Skyler 完成了。
【解决方案2】:
  1. 如果您想同步两个线程,您只需在装饰函数中添加锁,而不是装饰器本身。

  2. 没有简单的方法可以直接停止线程,唯一的方法是使用事件来通知它必须退出的线程。

对于线程装饰器,您可以查看pebble

【讨论】:

  • 看起来很有趣。
【解决方案3】:

也许信号量可以帮助装饰器,比如计算 1 到 1000 的阶乘:

import threading

from functools import wraps
from math import factorial


DIC = {}

def limit(number):
    ''' This decorator limits the number of simultaneous Threads
    '''
    sem = threading.Semaphore(number)
    def wrapper(func):
        @wraps(func)
        def wrapped(*args):
            with sem:
                return func(*args)
        return wrapped
    return wrapper

def async(f):
    ''' This decorator executes a function in a Thread'''
    @wraps(f)
    def wrapper(*args, **kwargs):
        thr = threading.Thread(target=f, args=args, kwargs=kwargs)
        thr.start()
    return wrapper

@limit(10)     # Always use @limit as the outter decorator
@async
def calcula_fatorial(number):
    DIC.update({number: factorial(number)})

@limit(10)
def main(lista):
    for elem in lista:
        calcula_fatorial(elem)


if __name__ == '__main__':
    from pprint import pprint
    main(range(1000))
    pprint(DIC)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-26
    • 2016-09-09
    • 2014-07-21
    • 2014-02-16
    • 2012-01-28
    • 2016-07-17
    • 2016-01-28
    相关资源
    最近更新 更多