简体   繁体   English

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

[英]How to run 2 threads in the same method without it freezing?

I'm creating a game, and I require 2 threads being run in the same method, however, only 1 of them is moving. 我正在创建一个游戏,我需要以相同的方法运行2个线程,但是其中只有1个正在移动。 The first thread counts in seconds, and the other one handles ingame power (no, this is not Five Nights at Freddy's). 第一个线程以秒为单位,另一个线程处理游戏中的力量(不,这不是在Freddy的《五夜》)。 My game already has quite alot of files, and I do not think showing them all is a good idea, I'll only show the method that starts both threads. 我的游戏已经有很多文件,我不认为将它们全部显示是一个好主意,我只会显示同时启动两个线程的方法。

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

As you can see, my "powerhandler" thread works perfectly, however the "secondcounter" thread does not work, and if I switch they're places, then only secondcounter works, and not powerhandler. 如您所见,我的“ powerhandler”线程工作正常,但是“ secondcounter”线程不起作用,如果我将它们切换为位置,则只有secondcounter可以工作,而powerhandler则不能。 What should I do? 我该怎么办?

EDIT: These are my thread codes, I have more threads, but right now I'm only using these 2: 编辑:这些是我的线程代码,我有更多的线程,但现在我只使用这些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();
            }
        }
    }

}

and

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;
            }
        }
    }
}

As you can see, my "powerhandler" thread works perfectly 如您所见,我的“ powerhandler”线程完美运行

As we can see? 如我们所见? See from what? 看什么? You have not shown us any output or described any behavior. 您尚未向我们显示任何输出或描述任何行为。

however the "secondcounter" thread does not work, 但是“ secondcounter”线程不起作用,

What do you mean it "does not work"? 您是什么意思“不起作用”? What would it do if it worked? 如果有效,该怎么办? What does it do instead? 它有什么作用呢?

and if I switch [their] places, then only secondcounter works, and not powerhandler. 如果我切换其位置,则只有秒计数器起作用,而不是powerhandler。

What does that mean, "switch their places?" “换位”是什么意思? Threads do not have "places." 线程没有“位置”。 Are you talking about the order in which you start them? 您是否在谈论启动它们的顺序?


One thing that might be a problem is here: 这里可能有问题的一件事是:

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

As soon as power reaches zero (approx 10 seconds after the thread is started), this thread is going to loop forever, using 100% CPU, to continually set Game.g.state = State.LOSE . power达到零时(线程启动后大约10秒),该线程将永远循环使用100%CPU,以继续设置Game.g.state = State.LOSE

That might not be what you intended. 那可能不是您想要的。

Using threads for things like this is not a good idea. 对于此类事情使用线程不是一个好主意。 Use a swing Timer instead, it will make a lot of things easier and safer. 而是使用swing 计时器 ,它将使很多事情变得更加容易和安全。

Thread safety 线程安全

A swing timer runs on the Event Dispatch Thread , that means you don't have to synchronize things for thread safety. swing计时器在Event Dispatch Thread上运行,这意味着不必为了线程安全而同步。
If you use threads and, for example, modify the power member variable from another thread, things could get weird: 如果使用线程,例如,从另一个线程修改power成员变量,事情可能会变得很奇怪:

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

This thread could be interrupted between if and power-- , and if another thread sets power to zero, power may be -1 in the end. 该线程可能在ifpower--之间中断,并且如果另一个线程将power设置为零,则power最终可能为-1
Such errors can be very difficult to find later, because the will only occur rarely. 这样的错误可能会非常困难以后找到的,因为只有很少发生。 Typically, when you are not debugging, but showing your program to someone else. 通常,当您不是在调试而是向其他人展示您的程序时。

InterruptedException InterruptedException

no need to deal with InterruptedException s with timers. 无需使用计时器处理InterruptedException

Performance 性能

should be better without creating many threads. 在不创建许多线程的情况下应该更好。

Simplicity 简单

Your code could be more readable with timers, you can handle timer events just like the other events. 计时器可以使您的代码更具可读性,您可以像处理其他事件一样处理计时器事件。

At the start of the method run, why not try to add Thread.yield(); 在方法运行开始时,为什么不尝试添加Thread.yield(); ?

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

In that case, the Thread will let other 'waiting' Thread to execute before continuing. 在这种情况下,该线程将让其他“等待”线程在继续执行之前执行。

Edit: Try to add the Thread.yield(); 编辑:尝试添加Thread.yield(); inside the while(true) loop 在while(true)循环内

I assumed you using this value somehow on gui (from EDT thread) and noticed it is not changing. 我假设您以某种方式在gui上使用了该值(来自EDT线程),并注意到它没有改变。 If that is the issue, you have visibility problem in your code, accessing variable across different thread without proper publishing/synchronization. 如果那是问题,则您的代码中存在可见性问题,跨不同线程访问变量而没有适当的发布/同步。

public static int seconds = 0;

Please use AtomicInteger from java.util.concurrent.atomic package. 请使用java.util.concurrent.atomic包中的AtomicInteger。

public static AtomicInteger seconds = new AtomicInteger(0);

and use 和使用

seconds.incrementAndGet();

instead of 代替

seconds++;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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