2013-07-10 6 views
1

У меня есть следующий код, который подсчитывает, сколько раз я посещаю нить. Код работает нормально, но я хочу узнать, можно ли реализовать это без какой-либо глобальной переменной.Подсчитайте, сколько раз я посещаю нить

import threading 
import lib.logging 
import time 

count = 0 

class Monitor(threading.Thread): 
    def __init__(self, count): 
     threading.Thread.__init__(self) 

    def run(self): 
     global count 
     count+=1 
     lib.logging.debug ("Count is: " + str(count)) 

def main():   
    for i in xrange(3): 
     t1 = Monitor(count) 
     t2 = Monitor(count) 
     t1.start() 
     t2.start() 
     t1.join() 
     t2.join() 
     time.sleep(3) 

    print "done" 

Большое спасибо

+0

Как конкретно вы хотите отследить его? Существует 'queue' и' pipe' для передачи данных между потоками напрямую, и 'Event' и' Condition', если вы хотите использовать управляемую событиями модель. –

+2

Можем ли мы получить дополнительную информацию? Что такое t1 и t2? Если вы хотите, чтобы count не был глобальным, вам нужно отображать его на уровне, который имеет доступ к местам, которые он может найти. В идеале, если оператор печати можно перенести на тот же уровень, что и основная функция, а затем добавить поле self.count в класс Monitor, может быть функция, которая проверяет значения count из всех классов монитора, а затем печатает сумма, если она изменилась. – mbdavis

ответ

1

Это можно считать вызов функции без глобальной переменной с помощью itertools.count и Питона функция аргументы по умолчанию поведение:

import threading 
import lib.logging 
import time 
from itertools import count 


class Monitor(threading.Thread): 
    def __init__(self): 
     threading.Thread.__init__(self) 

    def run(self, count=count()): 
     # next(count) starts from 0, so to log first '1', + 1 is used 
     lib.logging.debug ("Count is: " + str(next(count) + 1)) 

def main():   
    for i in xrange(3): 
     t1 = Monitor() 
     t2 = Monitor() 
     t1.start() 
     t2.start() 
     t1.join() 
     t2.join() 
     time.sleep(3) 

    print "done" 

Вот пост про аргументы питона функции по умолчанию: http://www.lexev.org/en/2013/python-mutable-default-arguments/

+0

Спасибо, это действительно интересно. – ilyaw77

1

Одним из возможных решений является использование «полу-сохранялось» в памяти счетчика.

Например

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


import threading 
import time 
import redis 


class RedisCounter(object): 

    def __init__(self, db, host, port, key, reset=False): 
     pool = redis.ConnectionPool(host=host, port=port, db=db) 
     self.conn = redis.StrictRedis(connection_pool=pool) 
     self.key = key 

     if reset: 
      self.initialize() 

    def initialize(self): 
     self.conn.set(self.key, 0) 

    def incr(self): 
     self.conn.incr(self.key) 

    def get(self): 
     return int(self.conn.get(self.key)) 


class Monitor(threading.Thread): 

    def __init__(self, counter): 
     threading.Thread.__init__(self) 
     self.counter = counter 

    def run(self): 
     self.counter.incr() 
     print("Count is: " + str(self.counter.get())) 


def main(): 
    counter = RedisCounter(0, 'localhost', 6379, 'thread_counter', True) 

    for i in xrange(3): 
     t1 = Monitor(counter) 
     t2 = Monitor(counter) 
     t1.start() 
     t2.start() 
     t1.join() 
     t2.join() 
     time.sleep(3) 

    print "done" 

if __name__ == '__main__': 
    main() 

Это может быть излишним для вас, но направление решения такой проблемы, тем не менее :)

+0

Большое спасибо woozyking, это действительно хороший пример для будущей справки, но немного переборщик для меня сейчас :) – ilyaw77

+0

@ ilyaw77 приветствуется :) Обычно я применяю эту технику к приложениям, которые могут нуждаться в горизонтальной масштабируемости, поэтому я делегирую состояний/счетчиков и, насколько это возможно, БД. – woozyking

Смежные вопросы