AsyncExecutor doesn’t seem asynchronous - java

This question has been edited to provide as much information about the problem as possible, as someone suggested I should do. Now that there’s bounty on it—that only seems like the right thing to do. Good luck, people!
Don’t forget you can always ask additional questions if you feel there’s something I didn’t include!
Introduction
I’m working on a system for procedurally generating terrain as a character walks around using various different noises—mostly perlin- and simplex-noise. The world itself has three dimensions, althought it’s viewed as top-down in two dimensions inside the game.
For those of you used to procedurally generating terrain, you’ll be aware of the fact that it’s necessary to use multithreading in order for it not to cause lag spikes within the renderer thread. That’s exactly what I’ve been trying to do, with a little help from LibGDX’s AsyncExecutor, as well as the same library’s AsyncTask, which is a task running on the thread offered by the AsyncExecutor.
Problem
My problem is that the AsyncExecutor doesn’t seem asynchronous at all. It causes lag spikes within my renderer thread, which in theory could be from it using a resource that also is used by the renderer thread. The thing is, however, that the renderer thread generates in new “chunks”—I call them regions—that the AsyncExecutor then work on. The renderer thread isn’t allowed to render that resource until it has been fully generated by the AsyncExecutor.
RegionHandler
I have a class called RegionHandler which places new regions in the direction the player is moving and removes regions from the opposite directions—in order for the program not having to be aware of more than 13 x 9 regions at one time.
Here’s a brief piece of code explaining how it works—the comments are there to simplify discussing different pieces of the code:
// These ‘if’s are triggered when the player moves
// to a certain position
if(addLeft)
{
// Adds new regions to the left and removes to the right
// ...
// Submit ‘RegionLoader’ task to ‘asyncExecutor’
// with regions that needs be generated as well as ‘toSends’ which is
// also part of that generation
asyncExecutor.submit(new RegionLoader(toGenRegions, toSends));
}
else if(addRight)
{
// Adds new regions to the right and removes to the left
// ...
// Same as previous ‘submit’ to the ‘asyncExecutor’
asyncExecutor.submit(new RegionLoader(toGenRegions, toSends));
}
if(addBottom)
{
// Adds new regions to the bottom and removes to the top
// ...
// Same as previous ‘submit’ to the ‘asyncExecutor’
asyncExecutor.submit(new RegionLoader(toSend, toSends));
}
else if(addTop)
{
// Adds new regions to the top and removes from the bottom
// ...
// Same as previous ‘submit’ to the ‘asyncExecutor’
asyncExecutor.submit(new RegionLoader(toSend, toSends));
}
The asyncExecutor is in fact and AsyncExecutor and the RegionLoader implements the AsyncTask interface. I’ve tested to see how long this piece of code takes to run through—this piece of code never takes over a single millisecond to run through.
The Regions are handled inside a list:
List<List<Region>> regions;
RegionLoader
This class is a task with the capability of being run by an AsyncExecutor.
private class RegionLoader implements AsyncTask<Object>
{
private List<Region> regions;
private List<ToSendInner> toSends;
public RegionLoader(
List<Region> regions,
List<ToSendInner> toSends)
{
this.regions = regions;
this.toSends = toSends;
}
#Override
public Object call() throws Exception
{
// Generates the ‘Region’s it has been given inside the constructor
// ...
return null;
}
}
Once call() has finished it’ll set a boolean to true that allows for the rendering of that specific Region.
Furthermore
Although the AsyncExecutor is meant to be asynchronous, it causes lag spikes every once in a while inside the renderer thread. As mentioned earlier, this could be caused by the AsyncExecutor using the same resources as the renderer thread, but the renderer thread merely renders the Regions when it’s allowed to—for that reason I can’t see why that’d be what’s causing the lag spikes.
What I’ve tried so far
I’ve tried using regular Java threads, but I read somewhere that these might not work due to LibGDX supporting Android development and Android doesn’t have the same capabilities when it comes to multithreading—but I could truly be wrong!
Furthermore
Perhaps someone has experienced a similar problem over their game development careers? If so, maybe someone can point me in the right direction?

I'd take a look into the effects of your garbage collection, as you seem to be passing new Region objects to the tasks. Try reusing/repopulating existing Regions instead.

I don't remember any problems about Android and Threads and searched but didn't find anything. You should test it.
I will assume that generating regions is not anything related to openGL. So you don't have to run it on main thread.
Try this: Thread + Gdx.app.postRunnable()
new Thread(new Runnable() {
Variables...
public Runnable set(Variables... ) {
// set variables
return this;
}
#Override
public void run() {
// do stuff
Gdx.app.postRunnable(() -> {
// commit that stuff.
});
}
}.set(regions,whateverelse)).start();
If you look at the source code of AsyncExecutor you will see that it exactly does the same. But only it doesn't let a second runnable run at the same time.
https://github.com/libgdx/libgdx/blob/9b8f20b2d0e96e53f0f2b98dc8f6131c810aae71/gdx/src/com/badlogic/gdx/utils/async/AsyncExecutor.java
Note: The implementation of the AsyncExecutor is changed to instantly execution in the gwt backend. Because of the limitations I'd guess. You probably shouldn't target gwt.
Try it, and let me know. If main thread still hangs, it is because what you are doing in the //commit that stuff part. Post more of your code, there is not enough to understand the source of the problem.
EDIT : Also use Gdx.graphics.getDeltaTime() to see if there is really a hang. It might be caused by something else, so eliminate other possibilities and find out if the real reason is this task.

Related

Read JSON files into collections, best practice

I'm working on a JavaFX application. I have several JSON files which I would like to read and insert into Collections in domain objects. I am using Gson to read these files at present. My application currently is working, however, there is a long delay before the application launches. I assume that this is because I'm reading these files sequentially and in the same Thread. Therefore, I am looking to enhance the launch time by introducing some concurrency. I'm thinking If I can figure out how to read the files in parallel it should speed up the launch time. I'm new to the idea of concurrency so I'm trying to learn as I go. Needless to say, I've hit a few roadblocks and can't seem to find much information or examples online.
Here are my issues:
Not sure if the JSON file reads can be done in a background thread.
Domain classes use these Collections to compute and eventually display values in the GUI. From my understanding, if you modify the GUI it has to be done in the JavaFX Application thread and not in the background. I'm not sure if loading data to be used in the GUI counts as modifying the GUI. I'm not directly updating any GUI Nodes like textField.setText("something") by reading Json, so I would assume no, I'm not. Am I wrong?
What is the difference between a Task> and Thread or an ExecutorService and Callable>? Is one method preferred over the other? I've tried both and failed. When I tried using a task and background thread, I would get a NullPointerException because the app tried to access the collection before the files were read and initialized with data. It went from being too slow to being too fast. SMH.
To solve this problem, I heard about Preloaders. The idea here was to launch some sort of splash screen to delay until the loading of resources (reading of JSON files) was complete, then proceed to the main application. However, the examples or information here is VERY scarce. I'm using Java 10 and IntelliJ, so I may have cornered myself into a one in a million niche.
I'm not asking for anyone to solve my problem for me. I'm just a little lost and don't know where or how to proceed. I'll be happy to share specifics if needed but I think my issues are still conceptual at this point.
Help me StackOverflow you're my only hope.
edit: code example:
public class Employee {
private List<Employee> employeeList;
public Employee() {
employeeList = new ArrayList<>();
populateEmployees();
}
private final void populateEmployees() {
Task<Void> readEmployees = new Task<>() {
#Override
protected Void call() throws Exception {
System.out.println("Starting to read employee.json"); // #1
InputStream in = getClass().getResourceAsStream("/json/employee.json");
Reader reader = new InputStreamReader(in);
Type type = new TypeToken<List<Employee>>(){}.getType();
Gson gson = new Gson();
employeeList.addAll(gson.fromJson(reader, type));
System.out.println("employeeList has " + employeeList.size() + " elements"); // #2
return null;
}
};
readEmployees.run();
System.out.println(readEmployees.getMessage()); // #3
}
}
I see #1 printed to the console, never #2 or 3. How do I know that it processed all through the Task?
How much your app will speed up depends on how big are those files and how much files there are. You should know that creating threads is also resource consuming task. I can imagine situation where you have plenty of files and for each one you're creating a new thread which could even make your app initialize slower.
In case of big amount of files or number of files which can change in time, you can arrange some thread pool of constant number eg. 5 which can work simultaneously on reading files task.
Back to the problem and the question is it worth to use separate threads for reading files, I'll say yes but only if your app have some work on initialization which can be done without knowing content of those files. You should be aware that in some point in time you'll probably need to wait for file parsing results.
As a part of problem solving you can do some benchmark to check how long parsing each file process takes and then you'll know what configuration/amount of working threads will be the best. Eg. you won't create thread for each file when parsing takes 1 second, but if you have 100 files of 1 second processing time you can create some thread pool and divide the job for each thread equally.
yes
I don't know JavaFX but in general concept of Thread and Task is the same. Thread gives you certanity that you're starting new thread, it's lower level of abstraction. Task is some sort of higher abstraction where you want to run part of your code separately, and asynchronously but you don't want to be aware on which thread it will run. Some programming languages behind Task hides actually some thread pool.
Preloaders are fine, because they show user some job is being done in background so he won't worry if application has frozen. On the other hand if you can speed up initialization process it will be great. You can join those two ideas, but remember, no one wants to wait a lot :)

SecondaryLoop in JavaFX, like Swing?

I have a Java Swing app which I'm investigating if it is even possible to port to JavaFX. The app is a development environment and simulator for an internally used scripting language. The interesting thing about it is you can set breakpoints for this scripting language and step through it, like any programmer would expect for a language.
Now because the language in the simulator is interpreted, deep within the execution of the interpreter, when it hits a breakpoint, it can pop back to the gui with a Java Swing SecondaryLoop class. So when the breakpoint is hit, it calls secondaryLoop.enter(). The gui is then active for the user to inspect variables and gui components are active. When the user hits "Continue" in the program, it calls secondaryLoop.exit() to continue execution of the interpreter. It wouldn't really be feasible for the interpreter to unwind it's entire state to go back to the primary loop, and then take up where it left off at exactly the same point. That's why the SecondaryLoop is invaluable in making it work.
Is this possible in JavaFX?
Yes, it's possible. You need to use the enterNestedEventLoop and exitNestedEventLoop methods (they are inside the com.sun.javafx.tk.Toolkit class). See this usage example:
// Make sure to import the FX Toolkit first
import com.sun.javafx.tk.Toolkit;
// This object will be used as a unique identifier to the nested loop (to
// block the execution of the thread until exitNestedEventLoop is called)
final Object loopLock = new Object();
// Simulate a long process thread (DB call, download, etc)
Thread longProcess = new Thread(new Runnable()
{
#Override
public void run()
{
// Sleep for 12 seconds to simulate a long process
try
{
Thread.sleep(12000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
// Setup a result to pass back to the enterNestedLoop() caller
String result = "Result of this long process";
// We are now done. Call exitNestedEventLoop() to unblock
// the enterNestedLoop() caller. This needs to run from
// the FX Thread so use Platform.runLater()
Runnable fxRunner = new Runnable()
{
public void run()
{
try
{
Toolkit.getToolkit().exitNestedEventLoop(loopLock,
result);
} catch (Throwable t)
{
t.printStackTrace();
}
}
};
Platform.runLater(fxRunner);
}
});
// Start that long process from the FX Thread
longProcess.start();
// The next call will block until exitNestedEventLoop is called, however
// the FX Thread will continue processing UI requests
Object result = Toolkit.getToolkit().enterNestedEventLoop(loopLock);
// Next statement will print: "Result of this long process"
System.out.println("Result is: " + result);
Now, before you use this be warned of two important things:
The com.sun.javafx.tk.Toolkit class is not part of the public API, so Oracle reserves the right of removing it without notice. I've been using it just fine from Java 7 to 8u51 so they could stay there forever, change package/names or disappear completely (unlikely).
Nested loops (and Swing's secondary loops) are great for flexibility and small applications but overusing them often comes with a price. Nesting to many loops (huge stack trace) will often cause "strange" behaviour in your applications since initial parts of your code might end up waiting four or five things ahead completely unrelated to them. I've seen FX nested loops causing "empty" exceptions in FX WebEngine executeScript() calls and duplicating keyboard preprocessing (when pairing FX+Swing) among other problems.
That said I would recommend using the javafx.concurrent.Task instead (if it makes sense). Using the Task class will require a bit more effort but I think it's the correct way of doing things and will probably save you lots of maintenance time.
For extra reference about the FX Task class see this great article: http://docs.oracle.com/javase/8/javafx/interoperability-tutorial/concurrency.htm
UPDATE: enterNestedEventLoop and exitNestedEventLoop will be part of the Java 9 public API (Platform class), more info in JDK-8090865
Hope this helps!

JavaFX - Task/Background processing - How to call multiple methods in a task?

I'm trying to teach myself JavaFX and stumbled over a problem I can't seem to fully understand even after reading anything remotely related I could find.
What I'm trying to do :
I basically want to run some quick processing in the background of my JavaFX application so to not block the UI for the user. While this is happening a UI element is put up which then should be removed as soon as the background process is finished.
So what I attempted to do was to just move those method calls into a Task which should then run without making the UI freeze.
Task task = new Task<Void>() {
#Override
protected Void call() {
step1();
step2();
step3();
}};
new Thread(task).start();
I want to call multiple methods of the class we're currently in, but what's happening instead is that only the first method gets invoked. It seems to me that after step1 has reached it's end it doesn't actually "return" to the Task. I've tried looking up how this works and what I could do but honestly didn't get any smarter. Basically all examples of threading and workers only included how to loop and do recurring things but I really just want a "single execution" but in background.
It's probably a really idiotic thing I'm trying to do and shows my little understanding of this but if anyone could point me into the right direction I'd be very thankful.
Thanks a lot!
Solution :
When working with JavaFX the use of "Platform.runLater(task)" is advisable since a normal Thread cannot interact with the UI. A IllegalStateException will be thrown and the thread is halted/canceled(?). The Task itself can remain unchanged but has to be handed to the Platform to execute it to prevent this issue. I changed that one line and everything was perfect afterwards.
I hope this might help someone, someday :-)

How to design a simple concurrent network graph (Java, Swing & JUNG)

I'm working on a network program for class and it has a bunch of "nodes" (currently, just different ports on my machine) that do some processing and talk to each other. I want to visualize the connections, and a while ago I built a simple visualization "monitor" with JUNG2. I want to update it now that my app is working. I chose JUNG primarily because it had great documentation and tutorials and I've never done graphing or GUIs with Java (no GUI work since Win32 and C++Builder :)).
I'll describe how I'm doing it, but my question is generally: is there a better way? These are my requirements (AFAICT):
The nodes don't move around when adding an edge (they currently do, and it's really annoying).
It can handle (not crash) maybe 50-100 updates per second.
Edge colors (would be really nice).
Labels on nodes (I think I have this already...)
I don't need directed edges, just static/consistent node ordering so you can determine which node is doing what without trying to read labels all the time.
I have a SparseMultigraph using FRLayout2 and a VisualizationViewer. Whenever the nodes do something interesting, they send a UDP packet with a little data to the monitor. It receives and assigns a pooled thread to it which inspects the packet and adds an edge, node, etc., based on the packet data. This thread calls one of these:
public void addVertex(String a) {
if (!graph.containsVertex(a)) {
System.out.println("Adding vertex "+a);
graph.addVertex(a);
}
freshenVertex(a);
}
public void toggleEdge(Edge e) {
EdgeTimer et = new EdgeTimer(e);
Thread t = new Thread(et, "EdgeTimer");
t.start();
}
(I can pool that last one easily enough.) The EdgeTimer adds an edge, waits, and removes the edge:
graph.addEdge(edge.getName(), edge.getA(), edge.getB());
Thread.sleep(1500);
graph.removeEdge(edge.getName());
Every second, an Updater thread updates the graph:
synchronized (graph) {
relaxer.pause();
layout.initialize();
relaxer.resume();
}
And lastly, a Pruner thread removes old vertexes if they haven't been heard from in a while--though this could change to coloring them red or something.
Given that I'm new to JUNG2 and basically hacked my way through this, I'm assuming that this is pretty bad (I know I need to improve the synchronizing already just by looking at this). Any ideas what I could do? I wish I could just modify the graph without reinitializing it as I think that might be why it's moving nodes around and it seems slow...but I don't know what much about JUNG and I have about a week left to work on it. :) I was thinking of modifying a ConcurrentSomethingOrOther and updating the viz based on that instead of doing it directly from the packets...
Thanks,
Josh
P.S.: I left out lots of code to keep this question shortish, but would be happy to add it if it'll help.

Putting method calls into an ArrayList?

I was adding a loading bar feature to my program in Java and I was wondering if I could set a list of processes that need to be done, so that it knows how many processes it needs to complete.
For example, saving them as strings?
ArrayList<String> processes = new ArrayList<String>();
processes.add("CSVWriter.createFileOfCompany(\"Random Company\");");
processes.add("FileConverter.convertCSVToXLS(classPath +
\"/Output/Random_Company.csv\");");
for (int i = 0; i < processes.size(); i++) {
// run process
// update loading bar
}
These aren't real methods to my program, but they are pretty similar to what I want to accomplish.
I'm sure this isn't the best way, but I want to have some way to create a list like this so I know how many processes there are before I run them. I have a system set up to break down these processes even further and show their progress, so this bar is pretty precise at the moment, but I have to number each of the processes =/.
Maybe I'm just missing the point. Creating progress bars is totally new to me.
If there are any good articles on progress bar creation, feel free to send them my way as well. Keep in mind that I'm not using an actual swing-based GUI. This bar is all S.O.P text.
Many thanks,
Justian Meyer
Closures will hopefully be coming soon in the next version of Java, but until then you can use anonymous classes implementing a known interface:
List<Runnable> jobs = new ArrayList<Runnable>();
jobs.add(new Runnable() {
public void run() {
CSVWriter.createFileOfCompany("Random Company");
}
});
jobs.add(new Runnable() {
public void run() {
FileConverter.convertCSVToXLS(classPath + "/Output/Random_Company.csv");
}
});
for (Runnable job : jobs) {
job.run();
}
Here's a scheme that just came to my mind:
interface WorkProcess
void setWorkUnits(int units)
void setArguments(Object obj1,...)
void execute()
So you encapsulate all your tasks with an interface that does execute as per the classic command pattern; it's also told (see below) how much work that job will probably take. You'll probably want some mechanism to pass data into these tasks for them to work with.
class WorkProcessFactory
static WorkProcess makeWorkProcess()
static int getTotalWorkUnitsAllocated()
static synchronized int reportWorkDone(int units)
static void addProgressListener(ProgressListener xxx)
When you have a job to do, you ask the factory to churn out one of these processes for you. In doing so, it does the estimate on work units and passes that to the WorkProcess it just created. It also keeps a tally of the total of those units for setting up the top of the progress indicator. One cool side effect of this is that you don't have to wait for all your jobs to be prepared: You can increment the maximum value for your progress report every time you add a job even as jobs are being processed and newly created; your bar will always show a realistic ratio.
You can stuff your WorkProcesses into a queue of some sort. ExecutorService comes to mind if your WorkProcess also implements the Runnable interface (which is a good idea). You'll be at liberty to process those jobs sequentially single-file or concurrently - whatever your execution queue machinery supports.
The WorkProcess' execute() method basically wraps the run() method (or maybe the other way around, since ExecutorService expects a run() method but our work unit magic is in execute()); but when that's done, it conscientiously calls back to reportWorkDone with the number of units it was told its job was worth. Upon receiving these reports, the factory has an updated value for units of work done, which it can report back to the snooping ProgressListener. That, in turn, updates the bar in the GUI.
Done. (I think). Probably needs some refining.

Categories

Resources