繁体   English   中英

为什么不能一次运行两个以上的线程?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM