简体   繁体   English

(可能)相当简单的Java多线程问题

[英](probably) Quite simple Java multi-threading issue

I'm making a platformer in which I make the player jump by, every 30ms, adding a small amount of force upwards. 我正在制作一个平台游戏,使玩家每30毫秒跳过一次,向上施加少量力。 I thought I'd use multi-threading, as I've done a little bit of it before and it seemed simple enough. 我以为我会使用多线程,因为之前已经做过一点,而且看起来很简单。 Anyway, I tried this: 无论如何,我尝试了这个:

public void jump() {
    new Runnable() {
        public void run() {
            for (int i = 0; i <= jumpForce; i++) {
                velocity.y++;
                System.out.println("Adding force");
                try {
                    wait(30);
                } catch (InterruptedException e) {}
            }
        }
    }.run();
}

Now, what I thought this would do is every loop from 0 to jumpForce (in this case 50), it adds 1 onto the y velocity variable then waits 30ms, but what actually happens is I get an error called: 现在,我认为这是从0到jumpForce的每个循环(在本例中为50),它将y速度变量加1,然后等待30ms,但是实际上发生的是我得到一个错误:

java.lang.IllegalMonitorStateException

and I have no idea what this means so can someone tell me what I'm doing wrong? 我不知道这意味着什么,所以有人可以告诉我我做错了什么吗?

The javadoc says for wait : javadoc说wait

This method should only be called by a thread that is the owner of this object's monitor. 此方法只能由作为该对象的监视器的所有者的线程调用。 See the notify method for a description of the ways in which a thread can become the owner of a monitor. 有关线程可以成为监视器所有者的方式的描述,请参见notify方法。

you own a monitor with a synchronized block, change your code to : 您拥有带有同步块的监视器,请将代码更改为:

synchronized (this) {
  wait(30);
}

If you want to execute this code in a different thread, than you should NOT invoke the run() method of the Runnable. 如果您希望在不同的线程来执行这个代码,不是你应该调用run()了Runnable的方法。 What you should do is create an instance of a thread and put your Runnable implementation in its constructor. 您应该做的是创建一个线程实例,并将您的Runnable实现放入其构造函数中。 Then invoke .start() . 然后调用.start()

 public void jump() {
        new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i <= jumpForce; i++) {
                    velocity.y++;
                    System.out.println("Adding force");
                    try {
                        Thread.sleep(30);
                    } catch (InterruptedException e) {}
                }
            }
        }).start();
    }

Also you should sleep() the thread in this case rather than wait() , because you have not taken the object lock. 同样,在这种情况下,您应该sleep()线程而不是wait() ,因为您尚未获取对象锁。 In order to implement what you need using wait(), the method jump() must be synchronized and another thread must invoke it. 为了使用wait()实现所需的功能,必须synchronized jump()方法,并且另一个线程必须调用它。

You are not multithreading, because you are not creating any threads. 您不是多线程的,因为您没有创建任何线程。
The Runnable is running in the same thread that is going to run it. Runnable在将要运行它的同一线程中运行。 If you want to create a new Thread you have to explicitly do so with new Thread(new Runnable()) and use Thread#start() . 如果要创建新线程,则必须使用new Thread(new Runnable())显式地执行此操作,并使用Thread#start()

Anyway, you probably just want to schedule a task so better to use a ScheduledExecutorService: 无论如何,您可能只想安排一个任务,以便更好地使用ScheduledExecutorService:

ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
ex.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
        // do something
    }
}, 0, 30, TimeUnit.SECONDS);

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

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