Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在一个全新的线程上启动某个类的每个实例?_Java_Multithreading - Fatal编程技术网

Java 如何在一个全新的线程上启动某个类的每个实例?

Java 如何在一个全新的线程上启动某个类的每个实例?,java,multithreading,Java,Multithreading,我正在写一个有趣的游戏,玩家可以让精灵跳跃并发射激光。它最多可以有三名玩家。我的类Sprite对于所有三个玩家都是一样的,只是根据玩家的不同,每个玩家都有不同的控制布局,这是在其结构中给出的。Sprite使用KeyListener来运行 为了让多个玩家同时做一些事情(比如发射激光或跳跃),我需要在一个单独的线程中创建每个Sprite对象。我知道我可以在Sprite类上使用implements Runnable,但是这只在新线程上运行run()方法中的代码。这不起作用,因为Sprite中有keyP

我正在写一个有趣的游戏,玩家可以让精灵跳跃并发射激光。它最多可以有三名玩家。我的类
Sprite
对于所有三个玩家都是一样的,只是根据玩家的不同,每个玩家都有不同的控制布局,这是在其结构中给出的。Sprite使用
KeyListener
来运行

为了让多个玩家同时做一些事情(比如发射激光或跳跃),我需要在一个单独的线程中创建每个
Sprite
对象。我知道我可以在
Sprite
类上使用
implements Runnable
,但是这只在新线程上运行
run()
方法中的代码。这不起作用,因为
Sprite
中有
keyPressed()
和其他不在新线程上的东西

我的想法是使用一个“helper”类,让
实现Runnable
,然后在其
run()
方法中创建新的
Sprite
对象。 然而,这似乎是一种混乱的方法。我有没有办法在一个全新的线程上创建所有新的
Sprite
对象(
KeyListener
s以及该线程中包含的所有对象)

代码:

public class Sprite() implements KeyListener { //I want this class on a brand new thread
    int x;
    int y;
    int width;
    int height;
    Image spriteImage; 

    //code/methods for stuff

    //key listeners:

    @Override
    public void keyPressed(KeyEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyReleased(KeyEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyTyped(KeyEvent arg0) {
        // TODO Auto-generated method stub

    }

}
public class SpriteStarter(/* Sprite class parameters go here */) implements Runnable{

    void run() {
        Sprite s = new Sprite(/*params*/);
    }

}
当前解决方案:

public class Sprite() implements KeyListener { //I want this class on a brand new thread
    int x;
    int y;
    int width;
    int height;
    Image spriteImage; 

    //code/methods for stuff

    //key listeners:

    @Override
    public void keyPressed(KeyEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyReleased(KeyEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyTyped(KeyEvent arg0) {
        // TODO Auto-generated method stub

    }

}
public class SpriteStarter(/* Sprite class parameters go here */) implements Runnable{

    void run() {
        Sprite s = new Sprite(/*params*/);
    }

}

class Linker() {
    public static void main(String args[]) {
        SpriteStarter s1 = new SpriteStarter();
        SpriteStarter s2 = new SpriteStarter();
        Thread t1 = new Thread(s1);
        Thread t2 = new THread(s2);
        t1.start();
        t2.start();
    }
}
编辑:

public class Sprite() implements KeyListener { //I want this class on a brand new thread
    int x;
    int y;
    int width;
    int height;
    Image spriteImage; 

    //code/methods for stuff

    //key listeners:

    @Override
    public void keyPressed(KeyEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyReleased(KeyEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyTyped(KeyEvent arg0) {
        // TODO Auto-generated method stub

    }

}
public class SpriteStarter(/* Sprite class parameters go here */) implements Runnable{

    void run() {
        Sprite s = new Sprite(/*params*/);
    }

}

好吧,经过大量的反馈,我很明显我的游戏应该是单线程的。我很抱歉没有意识到这一点,我没有做太多的游戏编程,所以这对我来说是一件新鲜事。我的新想法是有一个ArrayList,它在
keyPressed()上激发,将按下的键添加到列表中。在Sprite类中,我将有一个update()方法,它查看按下的键并相应地更新坐标。然后将通过java.awt.Timer以固定的间隔调用Update()。这似乎对我有用,但我不确定,所以请告诉我!再次感谢大家。此外,我仍然希望能够回答最初的问题(即:如何在新线程上启动类的每个实例),因为这对将来的程序可能会有所帮助

首先,让我们澄清一点:对象不会在线程上运行。他们什么都不跑,真的。他们坐在内存中等待一些线程执行他们的方法。这就是为什么你可以有比赛条件。两个线程可能试图同时访问同一内存(可能在同一对象上)。回答你的问题


做几次深呼吸,思考一下设计。您的输入不是多线程的(至少我猜是这样)。事件从操作系统上的某个设备(或者,根据您的评论,从框架抽象(如窗口面板))一个接一个地进入您的应用程序。通常,更新精灵只涉及琐碎的数学运算。这可以在向您提供事件的线程上在线完成

此外,与直接在线执行计算相比,为每个新事件启动一个线程可能会产生更多的开销(如果您想执行所描述的操作)。最重要的是,如果你在处理一个事件和一个新事件进来的时候会发生什么?您需要阻止向每个线程提交事件(使线程无用)或在线程本地队列中排队事件

但是。。娱乐。。假设更新每个精灵可能需要很长时间(这很愚蠢,你的游戏将无法运行)

每个雪碧需要一根线。在每个线程上,您都需要一个消息队列。当您启动每个线程时,会阻塞消息队列,直到消息到达。当消息到达时,线程将其弹出队列并进行处理。您需要在消息中对事件进行编码。消息需要按值传递到队列中。为简单起见,消息和事件可以是同一个类

最简单的方法是只为事件设置一个侦听器,并让该侦听器将适当的事件分派给相关的精灵。但是,如果您希望每个精灵侦听自己的事件,只需将它们添加到从精灵本身处理精灵事件的线程队列中即可

package sexy.multithreaded.sprites;

public class GameDriver implements EventListener {
    final EventDispatcher dispatcher;
    final Framework framework;
    final List<Sprite> sprites;

    GameDriver(Framework framework) {
        framework.addEventListener(self);
        self.framework = framework;
        sprites = new ArrayList<>();
        dispatcher = new EventDispatcher(sprites);
    }

    public static void main(String[] args) {
        // register for events form your framework
        Framework f = new Framework(); // or window or whatever
        new GameDriver(f).startGame(Integer.parseInt(args[0]));
    }

    void startGame(int players) {
        // initialize game state
        for (int player = 0; player <= players; player++) {
            Sprite s = new Sprite(player);
            sprites.add(s);
            s.start();
        }
        // and your event processing thread
        dispatcher.start();

        // loop forever
        framework.processEvents();
    }

    @Override
    void onEvent(Event e) {
        if (e == Events.Quit) {
            dispatcher.interrupt();
        } eles {
            dispatcher.q.put(e);
        }
    }
}

class EventDispatcher extends Thread implements Runnable {
    // setup a queue for events
    final Queue<Event> q;
    final List<Sprite> sprites;

    EventDispatcher(List<Sprite> sprites) {
        super(this, "Event Dispatcher");
        this.sprites = sprites;
        q = new BlockingQueue<>();
    }

    @Override
    void run() {
        while (!interrupted()) {
            Event e = q.take();
            getSpriteForEvent(e).q.put(e);
        }
        for (Sprite s : sprites) {
            s.interrupt();
        }
    }
}

class Sprite extends Thread implements Runnable {
    final int num;
    final Queue<Event> q;

    Sprite(int num) {
        super(this, "Sprite " + num);
        self.num = num;
        q = new BlockingQueue<>();
    }

    @Override
    void run() {
        while (!interrupted()) {
            Event e = q.take();
            handle(e);
        }
    }

    void handle(Event e) {
        // remember we assumed this takes a really long time..
        // but how do I know how to calculate anything?
        switch (e) {
            case Events.UP:
                   // try to do something really long...
                   waitForUpvoteOn("a/35911559/1254812");
               break; // (;
            ...
        }
    }
}
package sexy.multi-threaded.sprites;
公共类游戏驱动程序实现EventListener{
最终事件调度员;
最后框架;
最终列表精灵;
游戏驱动程序(框架){
框架。addEventListener(自我);
self.framework=框架;
sprites=newarraylist();
dispatcher=新的EventDispatcher(精灵);
}
公共静态void main(字符串[]args){
//从您的框架中注册事件
Framework f=new Framework();//或window或其他
新的游戏驱动程序(f).startGame(Integer.parseInt(args[0]);
}
无效开始名(智力玩家){
//初始化游戏状态

对于(int player=0;player)为什么您的精灵需要在单独的线程上运行?您可以实现SpriteService或SpritesManager类并从中控制精灵实例(整个生命周期)。只需抽象“从每个注册的按键将转到各自的keyPressed()方法,这些方法将在单独的线程上”不,Swing/AWT不是这样工作的。Swing是单线程的,所有事件按顺序在同一线程上调度。
keyPressed
/
keyreased
/等都是回调。对于您最初关于在不同线程上创建对象的问题,我不明白您在问什么,抱歉。我相信OP至少应该得到一些非常好的回答sic了解线程的工作原理,以及为UI框架分配事件线程的想法……大多数游戏大约有3个线程:1)从操作系统收集输入的线程(与Swing线程的功能相同),2)计算游戏性并呈现图形的线程,以及3)播放音频的线程。