[英]Why can't I run more than two threads at once?
我是线程技术的新手,如果我遗漏了一些显而易见的内容,请原谅。
这是我的代码(一场乌龟比赛):
(跳到线程部分的代码底部)
import turtle
from random import randint
import threading
n = turtle.Turtle()
n.speed(10)
n.hideturtle()
n.penup()
n.goto(-600, 300)
n.pendown()
for x in range(1, 51):
n.forward(12)
n.write(x)
n.forward(12)
n.right(90)
n.forward(270)
n.right(90)
n.forward(1200)
n.right(90)
n.forward(270)
n.right(180)
n.forward(15)
n.left(90)
for x in range(0, 4):
n.forward(1200)
n.right(90)
n.forward(30)
n.right(90)
n.forward(1200)
n.left(90)
n.forward(30)
n.left(90)
n.forward(1200)
n.right(90)
red = turtle.Turtle()
blue = turtle.Turtle()
green = turtle.Turtle()
orange = turtle.Turtle()
brown = turtle.Turtle()
black = turtle.Turtle()
pink = turtle.Turtle()
purple = turtle.Turtle()
turtles = {
red: ['red', 270],
blue: ['blue', 240],
green: ['green', 210],
orange: ['orange', 180],
brown: ['brown', 150],
black: ['black', 120],
pink: ['pink', 90],
purple: ['purple', 60]
}
for x in turtles:
x.color(turtles[x][0])
x.shape('turtle')
x.penup()
x.goto(-600, turtles[x][1])
def move_red(num1, num2):
for y in range(0, 240):
red.speed(randint(num1, num2))
red.forward(5)
return
def move_blue(num1, num2):
for y in range(0, 240):
blue.speed(randint(num1, num2))
blue.forward(5)
return
def move_green(num1, num2):
for y in range(0, 240):
green.speed(randint(num1, num2))
green.forward(5)
return
def move_orange(num1, num2):
for y in range(0, 240):
orange.speed(randint(num1, num2))
orange.forward(5)
return
def move_brown(num1, num2):
for y in range(0, 240):
brown.speed(randint(num1, num2))
brown.forward(5)
return
def move_black(num1, num2):
for y in range(0, 240):
black.speed(randint(num1, num2))
black.forward(5)
return
def move_pink(num1, num2):
for y in range(0, 240):
pink.speed(randint(num1, num2))
pink.forward(5)
return
def move_purple(num1, num2):
for y in range(0, 240):
purple.speed(randint(num1, num2))
purple.forward(5)
return
t1 = threading.Thread(target = move_red, args = [1, 10])
t2 = threading.Thread(target = move_blue, args = [1, 10])
t3 = threading.Thread(target = move_green, args = [1, 10])
t4 = threading.Thread(target = move_orange, args = [1, 10])
t5 = threading.Thread(target = move_brown, args = [1, 10])
t6 = threading.Thread(target = move_black, args = [1, 10])
t7 = threading.Thread(target = move_pink, args = [1, 10])
t8 = threading.Thread(target = move_purple, args = [1, 10])
ts = [t1, t2, t3, t4, t5, t6, t7, t8]
for x in ts:
x.start()
turtle.done()
如果在编辑器中运行此程序,您将看到乌龟随机停止。 当我运行2个线程时,不会发生这种情况。 .join()
也不起作用。 请向我解释为什么线程不起作用。
可以这样做,但是您需要将调用tkinter的乌龟操作限制在主线程中。 下面是我的拆卸和重建程序的工作方式,以这种方式删除多余的内容。 (我省略了可以添加的背景图。)我使用了线程安全队列数据结构在线程和tkinter之间进行通信:
from threading import Thread, active_count
from turtle import Turtle, Screen
from random import randint
from queue import Queue # use for thread-safe communications
QUEUE_SIZE = 1 # set higher the more unused hardware threads you have
COLORS = ['red', 'blue', 'green', 'orange', 'brown', 'black', 'pink', 'purple']
def move_turtle(turtle):
for _ in range(240):
actions.put((turtle.forward, randint(1, 10)))
def process_queue():
while not actions.empty():
action, argument = actions.get()
action(argument)
if active_count() > 1:
screen.ontimer(process_queue, 100)
actions = Queue(QUEUE_SIZE)
screen = Screen()
screen.setup(1200, 600)
threads = []
for y, color in enumerate(COLORS):
turtle = Turtle('turtle', visible=False)
turtle.color(color)
turtle.speed('fastest')
turtle.penup()
turtle.goto(-600, 270 - y * 30)
turtle.showturtle()
thread = Thread(target=move_turtle, args=[turtle])
threads.append(thread)
for thread in threads:
thread.start()
process_queue()
screen.mainloop()
我不希望海龟向前移动任意距离; 我希望他们以不同的速度前进相同的距离
您可以在我设置的环境中做到这一点:
def move_turtle(turtle):
for _ in range(240):
actions.put((turtle.speed, randint(1, 10)))
actions.put((turtle.forward, 5))
但是turtle.speed()
与绘制速度有关 ,您仅(而不是)绘制5像素线,因此绘制速度差别不大。 在比赛中途,这是正在发生的事情:
即使在比赛前将海龟设置为随机速度,而不更改它们,也没有任何区别。 我认为改变前进距离会使比赛更加精彩。
我制作了一个名为threaded_turtle
的库,该库使用的方式与@cdlane在他的答案中提供的方法相同,但是“智能”功能在后台工作。
您可以在gitlab上找到该库: https ://gitlab.com/zvone/threaded_turtle
这是与问题中相同的代码,经过修改可与threaded_turtle
库一起使用:
import turtle
from random import randint
from threaded_turtle import ThreadSerializer, TurtleThread
n = turtle.Turtle()
n.speed(10)
n.hideturtle()
n.penup()
n.goto(-600, 300)
n.pendown()
for x in range(1, 51):
n.forward(12)
n.write(x)
n.forward(12)
n.right(90)
n.forward(270)
n.right(90)
n.forward(1200)
n.right(90)
n.forward(270)
n.right(180)
n.forward(15)
n.left(90)
for x in range(0, 4):
n.forward(1200)
n.right(90)
n.forward(30)
n.right(90)
n.forward(1200)
n.left(90)
n.forward(30)
n.left(90)
n.forward(1200)
n.right(90)
red = turtle.Turtle()
blue = turtle.Turtle()
green = turtle.Turtle()
orange = turtle.Turtle()
brown = turtle.Turtle()
black = turtle.Turtle()
pink = turtle.Turtle()
purple = turtle.Turtle()
turtles = {
red: ['red', 270],
blue: ['blue', 240],
green: ['green', 210],
orange: ['orange', 180],
brown: ['brown', 150],
black: ['black', 120],
pink: ['pink', 90],
purple: ['purple', 60]
}
for x in turtles:
x.color(turtles[x][0])
x.shape('turtle')
x.penup()
x.goto(-600, turtles[x][1])
def move_red(red, num1, num2):
for y in range(0, 240):
red.speed(randint(num1, num2))
red.forward(5)
return
def move_blue(blue, num1, num2):
for y in range(0, 240):
blue.speed(randint(num1, num2))
blue.forward(5)
return
def move_green(green, num1, num2):
for y in range(0, 240):
green.speed(randint(num1, num2))
green.forward(5)
return
def move_orange(orange, num1, num2):
for y in range(0, 240):
orange.speed(randint(num1, num2))
orange.forward(5)
return
def move_brown(brown, num1, num2):
for y in range(0, 240):
brown.speed(randint(num1, num2))
brown.forward(5)
return
def move_black(black, num1, num2):
for y in range(0, 240):
black.speed(randint(num1, num2))
black.forward(5)
return
def move_pink(pink, num1, num2):
for y in range(0, 240):
pink.speed(randint(num1, num2))
pink.forward(5)
return
def move_purple(purple, num1, num2):
for y in range(0, 240):
purple.speed(randint(num1, num2))
purple.forward(5)
return
ctrl = ThreadSerializer()
t1 = TurtleThread(ctrl, red, target=move_red, args=[1, 10])
t2 = TurtleThread(ctrl, blue, target=move_blue, args=[1, 10])
t3 = TurtleThread(ctrl, green, target=move_green, args=[1, 10])
t4 = TurtleThread(ctrl, orange, target=move_orange, args=[1, 10])
t5 = TurtleThread(ctrl, brown, target=move_brown, args=[1, 10])
t6 = TurtleThread(ctrl, black, target=move_black, args=[1, 10])
t7 = TurtleThread(ctrl, pink, target=move_pink, args=[1, 10])
t8 = TurtleThread(ctrl, purple, target=move_purple, args=[1, 10])
ts = [t1, t2, t3, t4, t5, t6, t7, t8]
for x in ts:
x.start()
ctrl.run_forever()
但是,可以使代码更简单。 我会做这样的事情:
import turtle
import time
from random import randint
from threaded_turtle import ThreadSerializer, TurtleThread
def draw_background():
n = turtle.Turtle()
n.speed(10)
n.hideturtle()
n.penup()
n.goto(-600, 300)
n.pendown()
for x in range(1, 51):
n.forward(12)
n.write(x)
n.forward(12)
n.right(90)
n.forward(270)
n.right(90)
n.forward(1200)
n.right(90)
n.forward(270)
n.right(180)
n.forward(15)
n.left(90)
for x in range(0, 4):
n.forward(1200)
n.right(90)
n.forward(30)
n.right(90)
n.forward(1200)
n.left(90)
n.forward(30)
n.left(90)
n.forward(1200)
n.right(90)
def move_turtle(t, num1, num2):
for y in range(0, 240):
time.sleep(randint(num1, num2) * 0.02)
t.forward(randint(1, 10))
return
draw_background()
ctrl = ThreadSerializer()
colors = 'red', 'blue', 'green', 'orange', 'brown', 'black', 'pink', 'purple'
threads = []
for i, color in enumerate(colors):
t = turtle.Turtle()
t.color(color)
t.shape('turtle')
t.penup()
t.goto(-600, 270 - 30 * i)
threads.append(TurtleThread(ctrl, t, target=move_turtle, args=[1, 10]))
for thread in threads:
thread.start()
ctrl.run_forever()
另请注意,我使用的是time.sleep(randint(num1, num2) * 0.02)
,而不是t.speed(randint(num1, num2))
,因为如果您不这样做,那是减慢乌龟速度的正确方法想改变它移动的距离。
结果:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.