2017-11-06 17 views
1

私はいくつかの関数を持っていて、それらを異なるスレッドグループにしたい。つまり、私は別のスレッドグループが別のスレッドグループを実行するようにします。私の例のコードは以下の通りです:いくつかのスレッド関数をグループ化するPython

import threading 
from threading import Thread 

def func_a(): 
    # do something here 


def func_b(): 
    # do something here 

def func_c(): 
    # do something here 

def func_d(): 
    # do something here 

thread_a = threading.Thread(target = func_a) 
thread_b = threading.Thread(target = func_b) 
thread_c = threading.Thread(target = func_c) 
thread_d = threading.Thread(target = func_d) 

thread_a.start() 
thread_b.start() 
thread_c.start() 
thread_d.start() 

thread_a.join() 
thread_b.join() 
thread_c.join() 
thread_d.join() 

私が何をしたいのか、非常に簡単です。また、threading_group_bとしてfunc_cfunc_dを入れ、threading_group_aとしてfunc_afunc_bを置きます。最初にthreading_group_aを実行してからthreading_group_bを実行します。

+0

'thread_a.join()'と 'thread_b.join()'を使用する前に 'thread_c.start()'と 'thread_d.start()'はOKですか?またはより高い数のスレッドに対してこれを行う自動方法が必要なのでしょうか? – Adirio

+0

@RomanPerekhrest私は完全には同意しません、あなたが他のものを処理する前にいくつかの操作の結果が必要な状況があります。先物とプールはこのような状況を解決するためのものであり、非常に正当なユースケースのようです。 – Adirio

+0

@Adirioでは、先物やプールは非常に正当なユースケースになるとは言い難い* *実際にそれを証明する方が良い。あなたは適切な答えを投稿することでそれを証明することができます – RomanPerekhrest

答えて

0

あなたができることは、Poolを使用することです。これは、スレッドをグループ化して単一のタスクに割り当てる方法です。次に、特定のスレッドではなく、プールにタスクを割り当てます。あなたは4つの機能を持っていますが、2つしかありません。 pool.mapは、関数にいくつかの引数を通過するので、私は、関数のシグネチャを変更しなければならなかった

from multiprocessing.pool import ThreadPool 

def func_a(*args): 
    print 1 

def func_b(*args): 
    print 2 

pool = ThreadPool(3) 

pool.map(func_a, range(2)) 
pool.map(func_b, range(2)) 

11 

22 

注:だから、あなたはこれを行うことができます。ドキュメントにはのマップブロックが指定されており、結果はになるので、.join()を削除できます。


更新:可能です。あなたが+ bを一緒に実行する必要があるとしましょう。あなたはそれがないすべての第三の機能、でそれらをラップは、他の2つを呼び出していることができます。

def ab(*args): 
    func_a() 
    func_b() 

は、今すぐあなたのスレッドプールにab関数を渡します。関数から値を返す必要がある場合は、戻り値をリストに割り当て、そのリストを戻します。


アップデート2:

from multiprocessing.pool import ThreadPool 

def func_a(): 
    print 1 

def func_b(): 
    print 2 

def ab(*args): 
    func_a() 
    func_b() 

pool = ThreadPool(3) 
pool.map(ab, range(2)) 
+0

うーん...私の全体の機能を内部に置く方法はありますか?私のサンプルコードは単なる例に過ぎないことに注意してください。私がしたいのは、異なるスレッドグループでいくつかの関数を順番に実行することです。 – ryan9025

+0

@ ryan9025これはラッパー関数を使って行うことができます。私は私の答えを更新しました – Vinny

+0

ありがとう!そこで私は変数 'pool = ThreadPool(ab)'を作成しました。しかし、 'pool.map'の部分はどうですか? – ryan9025

0

考慮すべき2つの問題があります。

  1. あなたはマニュアルのために行くことができ

スレッドグループ化

  • フロー制御方法、を使用して3210秒またはグループにtupleの引数とスレッド自身、そしてまた、手動の流れを制御します。

    from threading import Thread 
    
    # Functions for group 1: with no arguments and different fucntions 
    def func_a(): 
        print(1) 
    
    def func_b(): 
        print(1) 
    
    # Functions for group 2: with a single function but different arguments 
    def func_c(i): 
        print(i) 
    
    # Functions for group 3: with different functions and arguments 
    def func_d(i): 
        print(i) 
    
    def func_e(i): 
        print(i) 
    
    funs_1 = (func_a, func_b) 
    args_2 = ((2,), (2,)) 
    funs_3 = (func_d, func_e) 
    args_3 = ((3,), (3,)) 
    
    threads_1 = tuple(Thread(target=func   ) for func in funs_1) 
    threads_2 = tuple(Thread(target=func_c, args=args) for args in args_2) 
    threads_3 = tuple(Thread(target=func, args=args) for func, args in zip(funs_3, args_3)) 
    
    for thread in threads_1: 
        thread.start() 
    
    for thread in threads_1: 
        thread.join() 
    
    for thread in threads_2: 
        thread.start() 
    
    for thread in threads_2: 
        thread.join() 
    
    for thread in threads_3: 
        thread.start() 
    
    for thread in threads_3: 
        thread.join() 
    

    または使用プール、あなたが開始されている可能同時スレッドのammountを指定することができ、および制御また、処理されます。

    from concurrent.futures import ThreadPoolExecutor 
    
    # Functions for group 1: with no arguments and different fucntions 
    def func_a(): 
        print(1) 
    
    def func_b(): 
        print(1) 
    
    # Functions for group 2: with a single function but different arguments 
    def func_c(i): 
        print(i) 
    
    # Functions for group 3: with different functions and arguments 
    def func_d(i): 
        print(i) 
    
    def func_e(i): 
        print(i) 
    
    funs_1 = (func_a, func_b) 
    args_2 = ((2,), (2,)) 
    funs_3 = (func_d, func_e) 
    args_3 = ((3,), (3,)) 
    
    with ThreadPoolExecutor(max_workers=5) as pool: 
        futures_1 = tuple(pool.submit(func) for func in funs_1) 
    
    with ThreadPoolExecutor(max_workers=5) as pool: 
        futures_2 = tuple(pool.submit(func_c, *args) for args in args_2) 
    
    with ThreadPoolExecutor(max_workers=5) as pool: 
        futures_3 = tuple(pool.submit(func, *args) for func, args in zip(funs_3, args_3)) 
    

    with文はプールが終了する前に、すべてのタスクを完了するようになります。 ThreadPoolExecutorインスタンスメソッドsubmit()を最初の引数にして、targetキーワード引数と同等のものを呼び出し、残りの位置引数とキーワード引数は、Threadargskwargsキーワード引数のような関数に渡されます。 concurrent.futuresはPython3の標準ライブラリにあり、Python 2.5以降に移植されているため、sudo pip install futuresを実行する必要があります。

  • +0

    ありがとう!しかし、私は 'args_1 =((1、)、(1))'と 'args_2 =((2、)、(2、)) 'は何かをよく理解していません。それは私の機能の出力を意味しますか?もしそうなら、私は自分の関数が実行される前に出力を持っていないという状況になっています...出力を置くのではなく、関数自体を 'args'に入れる他の方法はありますか?感謝!! – ryan9025

    +0

    これらは、関数に渡される引数です。それらをタプルに格納して反復できるようにしますが、タプルストアを使用しないThreadPoolExecutorアプローチの2番目のグループの例を確認できます。 – Adirio

    +0

    簡素化するために、私が望むのは、自分の関数自体を 'スレッド化'の 'target'に入れます。 – ryan9025

    関連する問題