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)播放音频的线程。