Java 如何在不冻结的情况下以相同的方法运行两个线程?

Java 如何在不冻结的情况下以相同的方法运行两个线程?,java,multithreading,Java,Multithreading,我正在创建一个游戏,我需要两个线程以相同的方法运行,但是,其中只有一个线程正在移动。 第一个线程以秒为单位计数,另一个线程处理ingame电源 (不,这不是弗雷迪家的五个晚上)。 我的游戏已经有相当多的文件,我不认为显示它们都是一个好主意,我将只显示启动两个线程的方法 @Override public void mouseClicked(MouseEvent e) { System.out.println(e.getX() + ", " + e.getY()); if (

我正在创建一个游戏,我需要两个线程以相同的方法运行,但是,其中只有一个线程正在移动。 第一个线程以秒为单位计数,另一个线程处理ingame电源 (不,这不是弗雷迪家的五个晚上)。 我的游戏已经有相当多的文件,我不认为显示它们都是一个好主意,我将只显示启动两个线程的方法

@Override
public void mouseClicked(MouseEvent e) {
    System.out.println(e.getX() + ", " + e.getY());
        if (e.getX() > game.panel.startbtnx
            && e.getX() < game.panel.startbtnx + 96
            && e.getY() > game.panel.getHeight() / 2
            && e.getY() < game.panel.getHeight() / 2 + 36) {
        if (game.state == State.MENU) {
            game.state = State.GAME;
            Ingame.alerts.add(new Alert("-9999 Points!"));
            Ingame.powerhandler.start();
            Ingame.secondcounter.start();
        }
    }
}


在方法运行的开始,为什么不尝试添加
Thread.yield()

见:

在这种情况下,线程将让其他“等待”线程在继续之前执行

编辑:尝试添加
Thread.yield()在while(true)循环中

正如您所看到的,我的“powerhandler”线程工作得非常好

如我们所见?看什么?您没有向我们显示任何输出或描述任何行为

但是“secondcounter”线程不工作

“不起作用”是什么意思?如果成功了,它会做什么?它的作用是什么

如果我切换[他们的]位置,那么只有secondcounter工作,而powerhandler不工作

这是什么意思,“切换位置?”线程没有“位置”。您是在谈论启动它们的顺序吗


这里可能有一个问题:

public void run() {
    ...
    while (true) {
        if (power > 0) {
            power--;
            ...
        } else {
            Game.g.state = State.LOSE;
        }
    }
}
一旦
power
达到零(线程启动后约10秒),该线程将使用100%的CPU永久循环,以持续设置
Game.g.state=state.LOSE


这可能不是您想要的。

对于类似的事情使用线程不是一个好主意。改用秋千,它会让很多事情变得更容易、更安全

线程安全性

swing计时器在事件调度线程上运行,这意味着您不必为了线程安全而同步事情。
例如,如果您使用线程并从另一个线程修改
power
成员变量,那么事情可能会变得奇怪:

if (power > 0) {
    power--;
    ....
此线程可能在
if
power--
之间中断,如果另一个线程将
power
设置为零,
power
最终可能是
-1

这种错误以后很难发现,因为这种错误很少发生。通常,当您不进行调试,而是向其他人显示您的程序时

中断异常

无需使用定时器处理中断异常

性能

在不创建多个线程的情况下应该更好

简单性


使用计时器可以使代码更具可读性,您可以像处理其他事件一样处理计时器事件。

我假设您在gui(从EDT线程)上以某种方式使用此值,并注意到它没有改变。如果这就是问题所在,那么代码中存在可见性问题,即在没有正确发布/同步的情况下跨不同线程访问变量

public static int seconds = 0;
请使用java.util.concurrent.atomic包中的AtomicInteger

public static AtomicInteger seconds = new AtomicInteger(0);
和使用

seconds.incrementAndGet();
而不是

seconds++;


您发布的信息不足以做出诊断。听起来好像你的后台线程根本不是后台线程。如果两个线程做的事情不一样,那么它们不应该在同一个方法中。一个方法只需要做一件事。@ JAMESHOLD,但它们都有不同的线程。睡眠。假设线程只在一个任务上循环,在每次执行该任务之间都有固定的延迟,您应该考虑使用A而不是管理自己的线程。也许我误解了您所说的“同一方法”的意思。我看到您有两种不同的运行方法。我尝试了,但secondcounter仍然不起作用,我将用这两种线程代码更新我的Q。您不应该期望
thread.yield()
调用来执行任何操作。您唯一应该使用它的地方是在繁忙的等待循环中,在某些体系结构中,它可能会提高服务员正在等待的任何其他线程的性能。但是,如果将它放入while(true)循环中,那么每次循环都会暂停,并将控制权交给另一个线程。我将它放在其中,第二个计数器仍然没有运行。@JFPicard这就是
Thread.yield()
的用途。它所做的唯一一件事,如果它真的做了什么的话,就是把CPU让给其他一些可运行的线程。这是一个毫无意义的调用:调用
Thread.yield()
,然后立即调用
Thread.sleep()
。另一种描述
Thread.yield()
功能的方法是,如果它有任何功能,那么它的功能与
Thread.sleep(0)
完全相同。谢谢,但是这并没有解决我的问题。@nestorishimo10:您是否将
Thread.sleep(…)
从if块中取出并放在while的开头(true)环不过更好的方法是使用Swing计时器,而不是使用这些后台线程。现在我这样做了,现在我得到了这个异常:
java.lang.InterruptedException:sleep interrupted在java.lang.Thread.sleep(本机方法)处,org.speedygoverment.CityPowerHandler.run(Ingame.java:88)在java.lang.Thread.run处(未知源代码)
第88行正好是线程所在的位置。sleep isAha,好的,我知道了。我现在就试试,我会在我完成itOk后报告,我将我的Power handling类更改为计时器(未扩展):但是它现在不工作。我还将用计时器替换
CityPower Handler
线程,仍然存在james large指出的问题。如果这样做之后,仍然存在问题,最好用更改的代码问一个新问题。我已经更改了CityPowerHandler。“好的,我将我的电源处理类更改为计时器”是的,对不起,我被
start
方法弄糊涂了。我的意思是:将两个线程都更改为计时器。顺便说一句,定时器有一个
重启
方法。
seconds.incrementAndGet();
seconds++;