2012-05-03 56 views
7

Tôi có một chương trình python sinh ra một số chủ đề. Những chủ đề này kéo dài từ 2 giây đến 30 giây. Trong chủ đề chính tôi muốn theo dõi bất cứ khi nào mỗi thread hoàn thành và in một tin nhắn. Nếu tôi chỉ tuần tự .join() tất cả các chuỗi và chuỗi đầu tiên kéo dài 30 giây và các chuỗi khác hoàn tất sớm hơn nhiều, tôi sẽ không thể in thư sớm hơn - tất cả thư sẽ được in sau 30 giây.Trong Python luồng, làm thế nào tôi có thể theo dõi hoàn thành một sợi?

Về cơ bản, tôi muốn chặn cho đến khi bất kỳ chuỗi nào hoàn thành. Ngay sau khi một chuỗi hoàn thành, in một thông báo về nó và trở lại để chặn nếu bất kỳ chủ đề khác vẫn còn sống. Nếu tất cả các chủ đề được thực hiện sau đó thoát khỏi chương trình.

Một cách tôi có thể nghĩ là có một hàng đợi được chuyển đến tất cả các chuỗi và chặn trên queue.get(). Bất cứ khi nào một tin nhắn được nhận từ hàng đợi, hãy in nó, kiểm tra xem các luồng khác có còn sống hay không bằng cách sử dụng luồng.active_count() và nếu như vậy, hãy quay lại chặn trên queue.get(). Điều này sẽ làm việc nhưng ở đây tất cả các chủ đề cần phải tuân theo kỷ luật gửi một tin nhắn đến hàng đợi trước khi chấm dứt.

Tôi tự hỏi nếu đây là cách thông thường để đạt được hành vi này hoặc có cách nào khác/tốt hơn không?

Trả lời

3

Dưới đây là một biến thể của câu trả lời @ detly của cho phép bạn chỉ định các thông điệp từ chủ đề chính của bạn, thay vì in chúng từ chức năng mục tiêu của bạn. Điều này tạo ra một hàm bao hàm gọi mục tiêu của bạn và sau đó in một thông điệp trước khi chấm dứt. Bạn có thể sửa đổi điều này để thực hiện bất kỳ loại dọn dẹp tiêu chuẩn sau mỗi thread hoàn thành.

#!/usr/bin/python 

import threading 
import time 

def target1(): 
    time.sleep(0.1) 
    print "target1 running" 
    time.sleep(4) 

def target2(): 
    time.sleep(0.1) 
    print "target2 running" 
    time.sleep(2) 

def launch_thread_with_message(target, message, args=[], kwargs={}): 
    def target_with_msg(*args, **kwargs): 
     target(*args, **kwargs) 
     print message 
    thread = threading.Thread(target=target_with_msg, args=args, kwargs=kwargs) 
    thread.start() 
    return thread 

if __name__ == '__main__': 
    thread1 = launch_thread_with_message(target1, "finished target1") 
    thread2 = launch_thread_with_message(target2, "finished target2") 

    print "main: launched all threads" 

    thread1.join() 
    thread2.join() 

    print "main: finished all threads" 
0

Tôi không chắc chắn tôi thấy vấn đề với việc sử dụng: threading.activeCount()

để theo dõi số lượng bài mà vẫn còn hoạt động?

Thậm chí nếu bạn không biết số lượng chuỗi bạn sẽ khởi chạy trước khi bắt đầu, có vẻ như bạn sẽ dễ dàng theo dõi. Tôi thường tạo ra các bộ sưu tập luồng thông qua việc đọc danh sách sau đó so sánh đơn giản bằng cách sử dụng activeCount với kích thước danh sách có thể cho bạn biết có bao nhiêu đã hoàn thành.

Xem ở đây: http://docs.python.org/library/threading.html

Cách khác, một khi bạn có thread của bạn đối tượng bạn chỉ có thể sử dụng phương pháp .isAlive trong các đối tượng thread để kiểm tra.

tôi chỉ kiểm tra bằng cách ném này vào một chương trình multithread Tôi có và có vẻ tốt đẹp:

for thread in threadlist: 
     print(thread.isAlive()) 

Cung cấp cho tôi một danh sách của True/False như các chủ đề bật và tắt. Vì vậy, bạn sẽ có thể làm điều đó và kiểm tra bất cứ điều gì sai để xem có bất kỳ chủ đề được hoàn thành.

1

Bạn có thể cho phép các chủ đề đẩy kết quả của chúng vào một threading.Queue. Có một chủ đề khác chờ đợi trên hàng đợi này và in tin nhắn ngay sau khi một mục mới xuất hiện.

4

Chủ đề cần được kiểm tra bằng cách sử dụng cuộc gọi Thread.is_alive().

2

Những gì tôi sẽ đề nghị là vòng lặp như thế này

while len(threadSet) > 0: 
    time.sleep(1) 
    for thread in theadSet: 
     if not thread.isAlive() 
      print "Thread "+thread.getName()+" terminated" 
      threadSet.remove(thread) 

Có một giấc ngủ 1 giây, vì vậy sẽ có một chút chậm trễ giữa việc chấm dứt chủ đề và thông điệp được in. Nếu bạn có thể sống với sự chậm trễ này, thì tôi nghĩ đây là một giải pháp đơn giản hơn giải pháp bạn đề xuất trong câu hỏi của mình.

3

Tại sao không chỉ có chủ đề tự in thông báo hoàn thành hoặc gọi một số cuộc gọi hoàn thành khác khi hoàn thành?

Bạn chỉ có thể join những chủ đề này từ chương trình chính của mình, vì vậy bạn sẽ thấy một loạt thư hoàn thành và chương trình của bạn sẽ chấm dứt khi tất cả được thực hiện, theo yêu cầu.

Dưới đây là một cuộc biểu tình nhanh chóng và đơn giản:

#!/usr/bin/python 

import threading 
import time 

def really_simple_callback(message): 
    """ 
    This is a really simple callback. `sys.stdout` already has a lock built-in, 
    so this is fine to do. 
    """  
    print message 

def threaded_target(sleeptime, callback): 
    """ 
    Target for the threads: sleep and call back with completion message. 
    """ 
    time.sleep(sleeptime) 
    callback("%s completed!" % threading.current_thread()) 

if __name__ == '__main__': 
    # Keep track of the threads we create 
    threads = [] 

    # callback_when_done is effectively a function 
    callback_when_done = really_simple_callback 

    for idx in xrange(0, 10): 
     threads.append(
      threading.Thread(
       target=threaded_target, 
       name="Thread #%d" % idx, 
       args=(10 - idx, callback_when_done) 
      ) 
     ) 

    [t.start() for t in threads] 
    [t.join() for t in threads] 

    # Note that thread #0 runs for the longest, but we'll see its message first! 
0

Tôi sử dụng kỹ thuật hơi khác vì tính chất của chủ đề tôi đã sử dụng trong đơn đăng ký của mình. Để minh họa, đây là một phần của chương trình thử nghiệm dây đeo mà tôi đã viết để xây dựng một lớp rào cản cho lớp luồng của tôi:

while threads: 
     finished = set(threads) - set(threading.enumerate()) 
     while finished: 
      ttt = finished.pop() 
      threads.remove(ttt) 
     time.sleep(0.5) 

Tại sao tôi làm theo cách này? Trong mã sản xuất của tôi, tôi có một giới hạn thời gian, do đó, dòng đầu tiên thực sự đọc "trong khi chủ đề và time.time() < cutoff_time". Nếu tôi đạt được giới hạn, tôi sẽ có mã để báo cho các chủ đề ngừng hoạt động.

Các vấn đề liên quan