2016-11-29 3 views
1

Я использую аналогичный код, как показано ниже, для управления полосой во главе с rgb, случайные значения поступают через каждые несколько секунд и создаются 3 потока для управления тремя отдельными цветами.Нити Python не закрываются после присоединения

import time 
from ast import literal_eval 
import threading 
from random import randint 
t=[] 
myR =0 
myG =0 
myB =0 
temp = 0 
pins = [17,22,24] 
myColours = [myR,myG,myB] 
red_pin = 17 
green_pin = 22 
blue_pin = 24 

def change_led_color(rgb): 
    global myR 
    global myG 
    global myB 
    y = 0 
    threads = [] 
    for colour in rgb: 
    t = threading.Thread(target=leds,name=pins[y] ,args=(y,myColours[y],colour,pins[y])) 
    threads.append(t) 
    y += 1 
    for y in threads: 
    y.start() 
    for y in threads: 
    y.join() 

def leds(index,start,end,pin): 
    temp=0 
    for i in range(start,end): 
    time.sleep(0.01) 
    temp = i 
    global myColours 
    print 'pin', pin, 'started at: ',start,' ended is: ', temp 
    myColours[index] = end 

def set_colours(): 
    print '..................................................................',t 
    print threading.activeCount(),'threads \n' 
    threading.Timer(2, set_colours).start() 
    change_led_color(t) 
set_colours() 

def get_data(): 
    while True: 
     global t 
     t = (randint(0,255),randint(0,255),randint(0,255)) 
     time.sleep(2) 
threading.Thread(target=get_data).start() 

Вышеприведенные работает нормально, но ответы очень странно, вместо того, чтобы получить все три цвета в конце резьбы, иногда я получаю больше, чем ожидалось, и в большинстве случаев, по крайней мере один будет 0, как нить никогда не запускается! Я предполагаю, что я неправильно использую резьбу.

например. результат

.................................................................. (187, 223, 42) 
3 threads 

pin 24 started at: 205 ended is: 0 
pin 22 started at: 170 ended is: 222 
pin 17 started at: 107 ended is: 186 
.................................................................. (202, 115, 219) 
3 threads 

pin 22 started at: 223 ended is: 0 
pin 17 started at: 187 ended is: 201 
.................................................................. (244, 35, 194) 
5 threads 

pin 22 started at: 115 ended is: 0 
pin 24 started at: 42 ended is: 218 
pin 17 started at: 202 ended is: 243 
pin 24 started at: 42 ended is: 193 
.................................................................. (54, 25, 72) 
3 threads 

pin 17 started at: 244 ended is: 0 
pin 22 started at: 35 ended is: 0 
pin 24 started at: 194 ended is: 0 
+0

Ваше предположение верно. Каждый раз, когда вы видите «глобальный» код потока, вы знаете, что, вероятно, это неправильно. –

+2

Есть ли причина, по которой вы фактически используете темы здесь? Почему бы не просто обновить три светодиода последовательно, учитывая, что обновление почти не займет времени? – chthonicdaemon

+0

Причина, по которой я использую потоки, заключается в том, что я пытаюсь добиться плавного перехода между изменениями, следовательно, использование 'for i in range..' для выполнения перехода трех цветов одновременно. –

ответ

1

Вы считаете GIL (Global Interpreter lock)? https://wiki.python.org/moin/GlobalInterpreterLock

Python имеет GIL, который не позволяет запускать несколько потоков из одного процесса. Когда вы запускаете свой код, он запускается как процесс python. Вы пытаетесь запустить потоки из одного процесса, который не разрешен в python.

Если вы хотите выполнить некоторые операции параллельно, пакет многопроцессорности является хорошим вариантом.
https://pymotw.com/2/multiprocessing/basics.html

+0

Спасибо @Tejas! Процессы нереста решили проблему, я больше не мог использовать «глобальный», но я работал вокруг нее, читая значения светодиодов в начале каждого процесса. –

+1

@Stratos. Причина, по которой многопроцессорность работает для вас, где потоковая передача не была такой, что вы «вы больше не обмениваетесь памятью между вашими потоками, поэтому у вас возникли проблемы. –

1

Не принимая во внимание другие факторы (см ниже) цикл for i in range(start,end): будет продолжаться до 2,5 секунд; но вы на самом деле порождаете новые потоки каждые 2 секунды.

Кроме того, фактическая продолжительность этого цикла на самом деле даже больше:

  • Всякий раз, когда вы просите сон, длительность, по крайней мере то, что вы просили; но это может быть немного больше. Особенно, когда вы просите 1/100 секунды, это может быть немного дольше.
  • Поскольку вы просите много маленьких спать один за другим, вы можете ожидать, что эффекты будут умножаться; Это означает, что общее время, проведенное в цикле for i in range(start,end): будет больше, чем ожидалось

Попробуйте:

  • Использование единого ожидания: time.sleep(0.01 * start-end if end>start else 0)
  • увеличить время, затрачиваемое на нерест новые темы для 3- 4 секунды