繁体   English   中英

主线程不断等待新线程

[英]Main thread keeps waiting on new threads

我正在尝试为我的项目编写一些“游戏引擎”,并且遇到线程问题。 当我在主流程中创建线程(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

您的问题是您在构造函数中创建了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();

它实际上并不是在启动新线程,而只是调用LoadThread.start()方法,该方法在同一线程中调用run()

public void start(){
    running = true;
    run();
}

编辑:

通过仔细查看提供的链接中的已发布代码,您正在LoadThread构造函数内部创建Thread对象。 这不是一个好的模式:

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

使用Runnable接口的方式存在一些问题:

  • runnable是包装代码的方式,以便可以在其他线程中启动它。 您应该重写run方法。 不要直接调用它,永远不要。
  • 要使用可运行对象,请包装到线程中并运行线程启动方法。 因此,您不应覆盖线程的start方法,也不要始终调用super.start()。
  • 为可运行对象提供启动方法只是一团糟。 包装线程的start方法将在新线程(包装器1)中调用可运行对象的run方法。 而已。 因此,如果您的可运行对象中有一个start方法,则包装线程将永远不会调用它。
  • 永远不要调用线程或可运行对象的run方法。 您会错过一点,因为该方法将在当前线程中执行,而不是在新线程中执行。
  • 不要同步运行方法,它只能由一个线程使用。

这是您应该采取的措施:

//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方法。

另外,如果您确实需要调用start,请考虑不使用可运行的方法,而是直接使用线程:

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

那要简单得多。

暂无
暂无

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

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