我正在尝试为我的项目编写一些“游戏引擎”,我遇到了线程问题。当我在主流程中创建一个Thread(LoadThread)时,它会一直等到Run();在LoadThread结束。
//loading thread
public class LoadThread implements Runnable{
private boolean running = false;
private Thread loader = null;
public LoadThread(/*init data structures*/){
loader = new Thread(this);
}
public void start(){
running = true;
run();
}
synchronized public void run() {
System.out.println(" loading started ");
while(running){
//do some loading, when done, running = false
}
System.out.println(" loading done ");
}
}
//holds data, starts loading
public class SourceGod {
private LoadThread img_loader;
public void startLoading(){
img_loader = new LoadThread(/* some data structures */);
img_loader.start();
}
}
//runs the game
public class Game extends GameThread implements ActionListener{
private SourceGod sources;
public Game(Window full_screen){
sources = new SourceGod(/* some data structures */);
System.out.println("before");
sources.startLoading();
System.out.println("after");
}
}
//own thread to refresh
abstract public class GameThread extends JPanel implements Runnable{
//anything from there is not called before "after"
}
输出
before
loading started
//some loaded data report, takes about 2-3s
loading done
after
任何帮助将不胜感激。 (更多代码http://paste.pocoo.org/show/orCfn9a8yOeEQHiUrgjG/) 谢谢, Vojtěch
答案 0 :(得分:5)
您的问题是您在构造函数中创建了一个Thread
对象,但是当您调用start()
时,您没有启动该线程,而是在同一个线程中运行run()
方法。这似乎是围绕扩展 Thread
与实施 Runnable
的混淆。
我认为你应该做的事情是:
// this should be of type Thread not LoadThread
private Thread img_loader;
...
// don't create the loader thread inside of LoadThread
img_loader = new Thread(new LoadThread(/* some data structures */));
img_loader.start();
LoadThread
是线程将执行的类型Runnable
的类。使用您当前的代码,当它调用时:
img_loader.start();
它实际上并没有启动新的Thread,它只是调用LoadThread.start()
方法,该方法在同一个线程中调用run()
:
public void start(){
running = true;
run();
}
修改强>
在您提供的链接中仔细查看已发布的代码时,您将在Thread
构造函数中创建LoadThread
对象。这不是一个好的模式:
public LoadThread(/*init data structures*/) {
// not recommended IMO
loader = new Thread(this);
}
再次,当您调用LoadThread.start()
时,您没有启动该线程,而是在同一个线程中调用run()
。我会改用new Thread(new LoadThread())
模式。如果您不得不包裹Thread
内的LoadThread
,那么您应该将LoadThread.start()
更改为:
// this should be removed, you want to call Thread.start() instead
public void start(){
running = true;
// this will start the internal thread which will call run()
loader.start();
}
顺便说一下,如果你想在另一个帖子中将running
设置为false,那么它应该被标记为volatile
。
答案 1 :(得分:0)
使用Runnable接口的方式有几个问题:
以下是您应该做的事情:
//loading thread
public class LoadThread implements Runnable{
/** Wether or not the thread is running. */
private boolean running = false;
/** Wrapper thread. */
private Thread loader = null;
public LoadThread(/*init data structures*/){
loader = new Thread(this);
}
public void start(){
running = true;
loader.start();
}
@Override
public void run() {
System.out.println(" loading started ");
while(running){
//do some loading, when done, running = false
}
System.out.println(" loading done ");
running = false;
}
}
如您所见,如果您想要一个start方法,只需调用包装器线程启动方法。
另外,如果你真的需要调用start,请考虑不直接使用runnable而是使用线程:
//loading thread2
public class LoadThread extends Thread{
/** Wether or not the thread is running. */
private boolean running = false;
@Override
public void run() {
running = true;
System.out.println(" loading started ");
while(running){
//do some loading, when done, running = false
}
System.out.println(" loading done ");
running = false;
}
}
这简单得多。