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

时间:2015-04-13 17:05:35

标签: java multithreading

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

@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();
        }
    }
}

正如你所看到的,我的“powerhandler”线程完美无缺 “secondcounter”线程不起作用,如果我切换它们的位置, 然后只有第二个计数器工作,而不是powerhandler。 我该怎么办?

编辑:这些是我的线程代码,我有更多的线程,但是现在我只使用这些2:

class SecondCounterHandler implements Runnable {

    public static int seconds = 0;
    public Thread thread;

    public void start() {
        thread = new Thread(this);
        thread.start();
    }

    @Override
    public void run() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        while (true) {
            try {
                Thread.sleep(1000);
                seconds++;
            } catch(InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

class CityPowerHandler implements Runnable {

    public int power = 100;
    public Thread thread;

    public void start() {
        thread = new Thread(this);
        thread.start();
    }

    @Override
    public void run() {
        Thread.yield();
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        while (true) {
            if (power > 0) {
                power--;
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                Game.g.state = State.LOSE;
            }
        }
    }
}

4 个答案:

答案 0 :(得分:1)

  

正如您所看到的,我的“powerhandler”主题完美无缺

我们可以看到?看什么?您没有向我们展示任何输出或描述任何行为。

  

然而“secondcounter”线程不起作用,

你是什么意思“不起作用”?如果有效,它会怎么做? 做什么呢?

  

如果我切换[他们的]位置,那么只有第二个计数器工作,而不是动力处理程序。

这是什么意思,“改变他们的位置?”线程没有“地方”。你在谈论你开始它们的顺序吗?


这可能是一个问题:

public void run() {
    ...
    while (true) {
        if (power > 0) {
            power--;
            ...
        } else {
            Game.g.state = State.LOSE;
        }
    }
}

一旦power达到零(线程启动后大约10秒),该线程将永远循环,使用100%CPU来连续设置Game.g.state = State.LOSE

这可能不是你想要的。

答案 1 :(得分:1)

使用线程来做这样的事情并不是一个好主意。使用摆动Timer代替,它会使很多事情变得更容易和更安全。

线程安全

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

if (power > 0) {
    power--;
    ....

此线程可能会在ifpower--之间中断,如果另一个线程将power设置为零,power最终可能会-1
此类错误可能 非常 以后很难找到,因为这种错误很少发生。通常情况下,当您调试,但将程序显示给其他人时。

<强> InterruptedException的

无需使用计时器处理InterruptedException

<强>性能

应该更好,不需要创建很多线程。

<强>简单

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

答案 2 :(得分:0)

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

请参阅:http://www.tutorialspoint.com/java/lang/thread_yield.htm

在这种情况下,Thread会在继续之前让其他'等待'Thread执行。

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

答案 3 :(得分:0)

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

public static int seconds = 0;

请使用java.util.concurrent.atomic包中的AtomicInteger。

public static AtomicInteger seconds = new AtomicInteger(0);

并使用

seconds.incrementAndGet();

而不是

seconds++;