Make Thread Wait on SimpleApplication Creation Before Continuing

I have a SimpleApplication called MultipleViews. I’m instantiating and starting it in a class on the EDT, and I find I have to make the EDT sleep for a second after the instantiation. It seems like when I instantiate and start MultipleViews, it continues this instantiation on a different thread (most notably during the execution of simpleInitApp()). If I don’t make the EDT sleep, then I get a NullPointerException when it tries to access some other part of MultipleViews because that part hasn’t been created yet.

Let me illustrate.

I’ve created a TopComponent in my NetBeans Platform Application. The TopComponent class runs on the EDT, and I have this code in my constructor to instantiate MultipleViews:

[java]
try
{
app = new MultipleViews();
Thread.sleep(1000);
}
catch (Exception e)
{

}

thisPanel = app.createNewPanel();
jPanel1.add(thisPanel, BorderLayout.CENTER);

[/java]

createNewPanel() is a method in MultipleViews that creates and returns a new AwtPanel.

Now, it works fine as is. However, if I take out the Thread.sleep(1000); line, I get the following error:

[java]Caused: java.lang.NullPointerException
at java.awt.Container.addImpl(Container.java:1090)
at java.awt.Container.add(Container.java:966)
at aero.sei.jme3sandbox4.Jme3SandboxTopComponent.<init>(Jme3SandboxTopComponent.java:77)[/java]

The error gets thrown at the last line, where I’m adding the AwtPanel to the JPanel.

I don’t like having to use Thread.sleep(1000), but some of the other methods I’ve looked at (Thread.join(), Futures and Callables, even lower millisecond values like Thread.sleep(500), etc.) all produce the same error. Only Thread.sleep(1000) works.

I need a more robust solution. I would appreciate any help the community can provide. Thanks in advance!

We would have to know more details about what else you’ve tried to be able to say why it doesn’t work.

Enqueuing a Callable on Application should be enough to know that the render thread is fully running. It won’t be run until the first update.

Well, here’s what else I’ve tried, all in the TopComponent constructor.

First, I tried just executing the constructor on another thread, then waiting for that thread to finish:

[java]Thread t = new Thread(
new Runnable() {
@Override
public void run()
{
app = new MultipleViews();
}
});
t.start();
try
{
t.join();
}
catch (Exception e)
{

}[/java]

I also tried using Futures and Callbacks:

[java]ExecutorService pool = Executors.newFixedThreadPool(4);

Future<MultipleViews> task = pool.submit(
new Callable()
{
@Override
public MultipleViews call()
{
return new MultipleViews();
}
});

try
{
app = task.get();
}
catch (Exception e)
{

}[/java]

But it all produces the same NullPointerException error.

For reference, here’s what’s running when I initialize MultipleViews():

[java]public MultipleViews()
{
setShowSettings(false);
AppSettings settings = new AppSettings(true);
settings.setCustomRenderer(AwtPanelsContext.class);
settings.setFrameRate(60);
setSettings(settings);
start();
ctx = (AwtPanelsContext) getContext();
}

@Override
public void simpleInitApp()
{

flyCam.setEnabled(false);

}
[/java]

Please let me know if I can provide more information. Thanks again.

What does “enqueuing a Callable on Application” mean?

@JCSW said: What does "enqueuing a Callable on Application" mean?

Well, there is an Application class. SimpleApplication subclasses this. This is what is calling simpleInitApp() so I assume you might know about this one.

So then the javadoc:
http://hub.jmonkeyengine.org/javadoc/com/jme3/app/Application.html

Where there is a method called “enqueue” that is for enqueuing callables that will run on the render thread… ie: the render thread must already be started and running before they are called.
http://hub.jmonkeyengine.org/javadoc/com/jme3/app/Application.html#enqueue(java.util.concurrent.Callable)

You could either wait for the callable to finish using its Future or just have the Callable call you back that the app is up and running.

@pspeed said: Well, there is an Application class. SimpleApplication subclasses this. This is what is calling simpleInitApp() so I assume you might know about this one.

So then the javadoc:
http://hub.jmonkeyengine.org/javadoc/com/jme3/app/Application.html

Where there is a method called “enqueue” that is for enqueuing callables that will run on the render thread… ie: the render thread must already be started and running before they are called.
http://hub.jmonkeyengine.org/javadoc/com/jme3/app/Application.html#enqueue(java.util.concurrent.Callable)

You could either wait for the callable to finish using its Future or just have the Callable call you back that the app is up and running.

I think I have an insufficient understanding of how threading works in jME3 when a SimpleApplication starts up. I thought all graphics rendering in Java happened on the EDT. If so, wouldn’t the jME3 rendering thread just be the EDT? The EDT is the thread that TopComponent runs on as well.

I overlooked enqueue() when studying the Javadoc for Application, so thank you for pointing that out. If I understand correctly, any Callable put on enqueue() will not run until after the main loop is up and running, meaning until after we call start() on the SimpleApplication and simpleInitApp() finishes running. Is this correct?

Thanks again for all of your help!

Threads I know are the Main thread, the AWT event loop, and the render loop. Plus various helper threads that are uninteresting because they don’t run user code, and possibly some Bullet handler threads, plus whatever you start manually.

You usually start your own threads from the render loop.

I have no idea what the EDT loop might be.

@toolforger said: Threads I know are the Main thread, the AWT event loop, and the render loop. Plus various helper threads that are uninteresting because they don't run user code, and possibly some Bullet handler threads, plus whatever you start manually.

You usually start your own threads from the render loop.

I have no idea what the EDT loop might be.

The EDT is the Event Dispatch Thread. However, it occurs to me as I’m writing this that the EDT is used for Swing rendering, which is different from rendering graphics in jME3. I assumed that all graphics rendering (not just Swing) happened on the EDT, but it looks like I might be mistaken.

Can you please break down what the Main, AWT event, and render threads each do in jME3? Can you also please explain what starting a thread from the render loop looks like?

Thanks again!

@toolforger said: I have no idea what the EDT loop might be.

Event Dispatch Thread, usually the same as or synced with the AWT event loop.

And for the record, even in swing/awt you can render to the screen from whatever thread you want to. It’s the Swing classes themselves that are not thread safe but you can make calls on a Graphics object from wherever you want.

It’s because Swing is not thread safe that you do everything swing-related on the EDT. Just like the rendered JME scene graph is not thread safe and you must do everything JME scene related on the OpenGL render thread.

@JCSW said: The EDT is the Event Dispatch Thread. However, it occurs to me as I'm writing this that the EDT is used for Swing rendering, which is different from rendering graphics in jME3. I assumed that all graphics rendering (not just Swing) happened on the EDT, but it looks like I might be mistaken.

Ah ok, I forgot that definition. In the thread display, that thread identifies itself as “AWT Event Handler” or something like that.

@JCSW said: Can you please break down what the Main, AWT event, and render threads each do in jME3? Can you also please explain what starting a thread from the render loop looks like?

The Main thread is just the thread that runs the main() function. In a typical JME application, it just calls new SomeSubclassOfApplication().start().

The AWT thread (EDT) is started with the first AWT window (all Swing windows are AWT windows, so it’s the same thing). It is stopped when there are no more AWT windows that can receive events, that is, after all windows have been closed and disposed (there is a dispose() function for JFrames and similar classes that you can have automatically called on close, or call explicitly).
I think @pspeed’s explanation is a bit misleading - from outside the EDT, you definitely shouldn’t draw on, say, a JPanel, because you’ll never know whether your draw calls go before or after those for borders or embedded components; you might have something work and find it break on other systems, or if the system load changes, or if you switch AWT from using heavyweight to lightweigt components.
Canvas might be an exception which is specifically built for drawing to it from outside the EDT. I have my doubts, but it’s not entirely impossible that Canvas was specifically designed for that use case; I’d still want to thoroughly verify that if I made use of that, and I’d probably go with drawing from inside the EDT anyway.

For JME applications, there are two variants: Those that use Fullscreen or Display mode, and those that use Canvas. Fullscreen/Display bypasses AWT entirely and directly uses the system-provided windowing and graphics API. Canvas uses a subclass of Canvas, to be embedded into an AWT window; i.e. in Canvas mode, you do indeed have an EDT; however, it does not redraw the Canvas component, that’s done by the render thread.

The OpenGL render thread (or render loop) is separate and independent of the EDT.
It does all the OpenGL API calls, and a typical JME application runs inside it almost entirely; you start worker threads from it (not by any design choice of the JME APIs but because you usually don’t start the game’s worker threads before the player has clicked through the start screens).
The render thread fills the same role for a JME application as the EDT for an AWT/Swing application.