I have a javaFX application which visualizes compuational geometry algorithms. The execution of an algorithm happens in another thread, lets call it mainComputingThread.
An algorithm can update the UI at any time by adding/removing/modifying shapes.
so the code will look like:
//do some computaions (1)
updateUI();
//do some more calculations (2)
What I want know is in the updateUI method to update the UI immediately and prevent the calling thread from running further (marked as (2)) until the UI update is done.
I thought about boolean guards. So the code could would look like:
updateUI(){
boolean guard = false;
Platform.runLater(new Runnable()
{
run(){
//do the actual update
guard = true;
}
});
while(guard==false);
}
I hope you get an idea of what I mean. I'm really curious if there's a better solution for this problem...
Simple approach: block background thread until update is complete:
You need to update the UI on the FX Application Thread. Typically you do this by passing a plain Runnable to Platform.runLater(...).
If you want to wait for that ui update to complete before proceeding, instead create a FutureTask and pass it to Platform.runLater(...). Then you can call get() on the FutureTask, which will block until the task is complete:
private void updateUI() throws InterruptedException {
// actual work to update UI:
FutureTask<Void> updateUITask = new FutureTask(() -> {
// code to update UI...
}, /* return value from task: */ null);
// submit for execution on FX Application Thread:
Platform.runLater(updateUITask);
// block until work complete:
updateUITask.get();
}
This lets the FutureTask handle all the tricky work of waiting and notifying: it is always better to use a higher-level API for this kind of work when you can.
If you like, you can refactor this into a utility method, similarly to Dainesch's answer:
public class FXUtils {
public static void runAndWait(Runnable run) throws InterruptedException {
FutureTask<Void> task = new FutureTask<>(run, null);
Platform.runLater(task);
task.get();
}
}
Alternative approach: ensure that no more than one update is consumed during any frame rendering, blocking the background thread if an update is pending
Here is a somewhat different approach. Create a BlockingQueue with a capacity of 1 to hold the Runnables that update the UI. From your background thread, submit the Runnables to the blocking queue: since the blocking queue can hold at most one element, this will block if one is already pending.
To actually execute the updates in the queue (and remove them, so more can be added), use an AnimationTimer. This looks like:
private final BlockingQueue<Runnable> updateQueue = new ArrayBlockingQueue<>(1);
background thread code:
// do some computations...
// this will block while there are other updates pending:
updateQueue.put(() -> {
// code to update UI
// note this does not need to be explicitly executed on the FX application
// thread (no Platform.runLater()). The animation timer will take care of that
});
// do some more computations
Create the timer to consume the updates:
AnimationTimer updateTimer = new AnimationTimer() {
#Override
public void handle(long timestamp) {
Runnable update = updateQueue.poll();
if (update != null) {
// note we are already on the FX Application Thread:
update.run();
}
}
};
updateTimer.start();
This basically ensures that no more than one update is ever scheduled at any time, with the background thread blocking until any pending updates are consumed. The animation timer checks (without blocking) for pending updates on each frame rendering, ensuring that every update is executed. The nice thing about this approach is that you can increase the size of the blocking queue, effectively keeping a buffer of pending updates, while still ensuring no more than one update is consumed during any single frame rendering. This might be useful if there are occasional computations that take longer than others; it gives these computations a chance to be calculated while others are waiting to be executed.
Hard question to answer without having the reason why you want to stop processing before the UI update is done. (Note: the runLater method executes the UI updates in the order received) Is it to prevent spamming to many Runnables to the JavaFX thread? Other reasons?
Your basic idea however works with the use of a CountDownLatch so that the processing thread waits to acquire a permit. If you choose that approach use something like this:
public class MyFXUtils {
public static runAndWait(final Runnable run) {
final CountDownLatch doneLatch = new CountDownLatch(1);
Platform.runLater(new Runnable() {
public void run() {
try {
run.run();
} finally {
doneLatch.countDown();
}
}
});
doneLatch.await();
}
}
EDIT: replaced Semaphore by CountDownLatch
EDIT:
So, the quickest way I always do it in prototypes is as following, transform:
//do some computaions (1)
updateUI();
//do some more calculations (2)
into
ExecutorService executor = Executors.newFixedThreadPool(1);
class JobStep implements Runnable {
public void run() {
doSomeComputations();
Platform.runLater(() -> {
updateUI();
executor.submit(new JobStep());
});
}
executor.submit(new JobStep());
OLD PART
Not an answer, but a suggestion how to attack the problem.
From my experience, the complete solution would be much more elaborate. I would separate the JavaFX shape instances from the shapes, which your algorithm does process. I would do it by means of using different class types and synchronize between the two.
The graphical algorithms have the tendency to be a lot quicker than the ones that are visualizing it. If the algorithm runs on small data set, then the rendering most often tend to slow down it significantly. It can easily be seen by running the same algorithm with and without visualization.
If the data set is bigger than the most trivial ones, then drawing of a single frame can easily take more than one second. Interactive visualizations are expected to respond in "real time", preferably many times per second.
The data visualization facilities have many means to tackle the problem. The best candidates always include:
Simplifying visualization. Drawing simpler shapes instead of complex, like removing the rounding from boxes. The LOD (level of detail) also applies to this point: during interactive scroll the visualized elements might be replaced by bounding box counterparts.
Selective hiding. Drawing only a part of the whole data set.
Parallelizing and hardware acceleration. The GPU's natively provide many means to handle complex visualizations. Typically the low level programming APIs (OpenGL, shader programs) allow much better throughput than every high level wrapping API, including JavaFX
Most often, the end solutions incorporate not only above points, but also others, including domain specific optimizations.
The visualization facilities always come with a lot of restrictions, like the most common one: have to be updated in the dedicated thread (thread confinement approach). They also come with visualization specific data structures.
From the data processing algorithm stage, one of the most common requirements is that it cannot be blocked or delayed by visualization. The algorithms are also written in a style, which doesn't translate to well for the means of visualization: imperative loops over data structures instead of updating observable drawable objects. There is a good reason to it though: the algorithms are expected to be optimized for performance or memory consumption.
One architectural approach to the problem might be as following:
The data processing stage produces snapshots at predefined points. The adding, modifying and remove operations are all published as this packet. It can be a just a copy of data structure that is being processed or it can be in the form of the coalesced events.
The data processing and data visualization run on different threads. They communicate only by means of publishing snapshots, never by blocking each other directly.
The snapshots shouldn't be restricted to particular frame rate. There should be means to batch updates before drawing or drawing same batch multiple times if the data processing stage stalls.
I strongly recommend reactive approach to the problem. The RxJava provides nice example for the "suggestion box" feature. It's very good at correctly handling requirements like "Every key update do a long running process on different thread and discard the last one, if any was running. Or maybe, don't do it on every key update, but wait 50ms for the user to make up his mind before he ends typing".
Related
I'm student and I'm working on project with few of my friends. My task is to make something like class library. Classes in this library should provide API for my friend who must make GUI part of application. GUI could be made by any toolkit (Swing, JavaFX, SWT, AWT, all should work, in fact, it should work even if there is no GUI). I need to make class that waits for data to arrive from network. I don't know when data will arrive, and UI must be responsive during waiting, so I put that in different thread. Now problem is how to make GUI respond when data arrive. Well, I tought that this is asynchronous event and GUI should register event handlers, and I should call that methods when event happens. I proposed this solution:
interface DataArrivedListener{
void dataArrived(String data);
}
class Waiter{
private DataArrivedListener dal;
public void setDataArrivedListener(DataArrivedListener dal){
this.dal = dal;
}
void someMethodThatWaitsForData(){
// some code goes here
data = bufRdr.readLine();
//now goes important line:
dal.dataArrived(data);
// other code goes here
}
}
My question is:
Should I replace "important" line with something like this:
java.awt.EventQueue.invokeLater(new Runnable(){
#Override
public void run(){
dal.dataArrived(data);
}
});
Or something like:
javafx.Platform.runLater(new Runnable(){
#Override
public void run(){
dal.dataArrived(data);
}
});
Or maybe I should do something completely different?
Problem is that I'm not sure which of this will work for any type of UI. If it's GUI, dataArrived() could potentialy make changes to GUI and no matter what type of GUI it is, this changes should be drawn on screen properly. I also think that it is better if I do "invoke this code later" so that my someMethodThatWaitsForData() method could trigger event and continue on with it's on work.
I appreciate your help.
Here's an Event Listener article I wrote a while back. The article explains how you write your own event listeners.
You're correct in that you want to write your own event listeners if you want your library to work with any GUI.
I'm most familiar with Swing, so yes, you'll have GUI code that looks like this:
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent event){
dal.buttonPressed(data);
}
});
If you want it to be completely agnostic to what GUI is being used the only real solution is to let the receiver handle it in dataArrived. Since every toolkit has its own implementation all you can really do to make it work with any toolkit is to disregard it. Otherwise what you will actually end up with is a list of "supported toolkits" and a case for each one.
If you just want dataArrived to be executed away from someMethodThatWaitsForData then you could make your own dispatch thread or make a new thread each time.
If you want to be truly independent of any front-end system, I would recommend creating two threads. The first is your Waiter, which will just listen for events and put them into a Queue of some sort (see the "All Known Implementing Classes" section). The second will invoke the data listener or listeners whenever the queue is not empty.
The concept of invoking a Runnable in the background is kind of deprecated since the invention of the concurrent package. The main reason that this was done in earlier days, is that the GUI code needs to be executed in a different thread, to guarantee that it stays responsive, even if the main thread is busy doing some calculations, but actual multi-threading was still in its very early days. The resulting invokeLater concept works, but comes with a strong creation overhead. This is especially annoying if you frequently have to do minor things, but each time you need to create an entire new Runnable, just to get that event into the Swing thread.
A more modern approach should use a thread-safe list, like a LinkedBlockingQueue. In this case any thread can just throw the event into the queue, and other listener/GUI-Event-handlers can take them out asynchronously, without the need of synchronization or background Runnables.
Example:
You initialize a new Button that does some heavy calculation once it is pressed.
In the GUI thread the following method is called once the button is clicked:
void onClick() {
executor.submit(this.onClickAction);
}
Where executor is an ExecutorService and the onClickAction a Runnable. As the onClickAction is a Runnable that was submitted once during Button creation, no new memory is accessed here. Let's see what this Runnable actually does:
void run() {
final MyData data = doSomeHeavyCalculation();
dispatcher.dispatch(myListeners, data);
}
The dispatcher is internally using the LinkedBlockingQueue as mentioned above (the Executor uses one internally as well btw), where myListeners is a fixed (concurrent) List of listeners and data the Object to dispatch. On the LinkedBlockingQueue several threads are waiting using the take() method. Now one is woken up as of the new event and does the following:
while (true) {
nextEvent = eventQueue.take();
for (EventTarget target : nextEvent.listeners) {
target.update(nextEvent.data);
}
}
The general idea behind all this, is that for once you utilize all cores for your code, and in addition you keep the amount of objects generated as low as possible (some more optimizations are possible, this is just demo code). Especially you do not need to instantiate new Runnables from scratch for frequent events, which comes with a certain overhead. The drawback is that the code using this kind of GUI model needs to deal with the fact that multi-threading is happening all the time. This is not difficult using the tools Java gives to you, but it is an entire different way of designing your code in the first place.
I'm writing a game in which a thread - GameThread - loops forever, updating all my sprites, rendering them, and then sleeping for some time before doing it all again. I also have a custom-made Event handler which deals with key presses etc.
This all works fine in most cases. However I have a problem if an event is thrown while GameThread is rendering. On rare occasions, the handler that deals with the event may make a concurrent change to what needs to be rendered affecting the results of the GameThread rendering.
To avoid this, I want the event handler to pause the GameThread immediately, handle the event, then resume GameThread.
The suspend() / resume() methods suit my needs, but they were deprecated. In my case, however, as there is little chance of a deadlock, is it safe to use them regardless?
If no, what other alternatives do I have that don't have a huge amount of overhead?
I have seen a suggestion of requesting a thread to pause by setting a flag in the Thread to be paused. In my case, however, I don't see that as a viable option since the GameThread loop may take a while during an iteration through the loop. I won't be able to check the flag until I'm done with the loop and by then it is too late.
I need immediate pausing, or else the user will notice a delay in the event handling.
If you want to synchronize access to resources, use a ReentrantLock:
ReentrantLock sync = new ReentrantLock();
You'd have to pass that lock to each runnable where you want to access the shared data.
Then in each place you're accessing the resource in question, you would use that shared lock object, and obtain and release the lock (ie, your critical sections):
sync.lock();
try {
// critical section code here
}
finally {
sync.unlock();
}
This is pretty standard concurrent programming in java. Keep in mind "lock" is a blocking method, so you might want to use "tryLock" instead, which allows you to try and acquire the lock, but returns a boolean as to whether or not you actually got the lock:
if (sync.tryLock()) {
try {
//critical section
}
finally {
sync.unlock();
}
}
There's a version of "tryLock" which will wait a given amount of time, before it will give up trying to acquire the lock and return a false value.
Usually, you would do some thread synchronization:
http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
This would let you do one of the two things you are doing: either render in the game rendering thread or do the changes based on your events.
The problem you are facing seems to be that your rendering code is taking too long for you to actually have a smooth experience (i.e. a lot of events can pile up for processing while you are rendering something). In that case, you should make your rendering out of independent pieces that can finish quickly and synchronize on them.
Without any code I cannot give you a specific advice, however in general it would look something like this:
List<Shape> shapesToRender;
Object lockObject = new Object(); // Note this must be somehow shared between two threads
// Your rendering thread method
public void renderForever() {
while(true) {
for(Shape shape: shapesToRender) {
synchronized(lockObject) {
render(shape);
}
}
}
}
// One of your event handlers
public void handleEvent(Event event) {
synchronized(lockObject) {
// Process event somehow, e.g. change the color of some of the shapes
event.getShape().setColor(Color.RED);
}
}
With the above, either:
You will be rendering one shape (and all your event handlers will be waiting for that to finish), or
Some of your event handlers will be doing something (and your rendering thread will be waiting for that to finish)
You should look at this Java trail in more depth:
http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html
as there are other solutions, e.g. using lock objects:
http://docs.oracle.com/javase/tutorial/essential/concurrency/newlocks.html
or concurrent collections:
http://docs.oracle.com/javase/tutorial/essential/concurrency/collections.html
that, depending on your problem, might be easier and, most importantly, very well tested solutions that would allow you to do something in a standard way, thus avoiding all the pitfalls that you can get into when rolling out custom threading code.
Hope this helps.
The suspend() / resume() methods suit my needs, but they were deprecated. In my case, however, as there is little chance of a deadlock, is it safe to use them regardless?
Obviously, if there is ZERO chance of a deadlock then it is safe. But there are all sorts of unexpected ways to get a deadlock. For instance, you could happen to pause a thread while it is initializing a class ... and that would deadlock any other thread trying to refer to a static field of that class. (This is a consequence of a specified behaviour of the JVM. There are other places where the locking / synchronization that goes on under the hood is not specified. Fair enough. It doesn't need to be ... unless you are contemplating using these deprecated methods.)
So, the reality is that it is really difficult to determine (prove) if it is actually safe. And if you can't determine this, then it is a potentially risky thing to do. That's WHY the methods are deprecated.
(Strictly speaking, this is not a deadlock. A deadlock is when the threads can never proceed. In this case, the other threads can proceed if you can resume the paused thread.)
I am writing a simple top down space game, and am extending it to allow play over a network with multiple players. I've done a fair bit of reading, but this is the first time I've done this and I'd appreciate some advice on choosing a sensible design.
My GUI is written using Swing. 30 times a second, a timer fires, and repaints my GUI according to data in a gameWorld object in memory (essentially a list of ships & projectiles with positions, etc). Physics updates of the gameWorld are also carried out using this timer. Thus, for the single player implementation, everything happens on the EDT, and this works fine.
Now, I have separate thread dealing with incoming packets from other players. I would like to update the data in my gameWorld object based on what these packets contain. My question is, should I use invokeLater to make these changes, or should I use locks to avoid concurrency problems?
To illustrate what I mean:
runMethodOfInputThread() {
while(takingInput) {
data = receiveAndInterpretIncomingPacket(); // blocks
SwingUtilities.invokeLater(new Runnable() {
public void run() {
gameWorld.updateWithNewGameInfo(data);
}
});
}
}
vs
runMethodOfInputThread() {
while(takingInput) {
data = receiveAndInterpretIncomingPacket(); // blocks
synchronize (gameWorldLock) {
gameWorld.updateWithNewGameInfo(data);
}
}
}
The latter would also require using similar synchronize blocks wherever the EDT accesses the gameWorld, so it seems to me that using invokeLater would be simpler to implement. But am I right in thinking both approaches would work? Are there any other significant pros/cons to bear in mind?
Thanks,
Jeremy
Well, first of all you don not need to choose only one method. You can use locks to make you data structure thread-safe "just to be sure" (since your application is already multithreaded), and use invokeLater to actually apply changes only in EDT -- and in this case JIT likely to optimize you locks down, close to 0.
Next, from my point of view invokeLater is rather preferred way: if you can way around dealing with multi-threaded -- you should use the way, just because multithreading is hard and rich of possible errors.
But applying changes via invokeLater() will put additional pressure on EDT, so, if changes come with high rate you can observe GUI degradation. Also, if gameWorld.updateWithNewGameInfo(data) is havy method taking observable time to complete, it can makes you GUI even freeze. Also, invokeLater puts your task at the tail of event queue, so it'll be done after all events currently in queue. It may -- in some cases -- cause delays in applying changes, which can makes you game less user-friendly. It may, or may not be your case, but you'll should keep it in mind
As for general rule -- not use EDT for any time consuming task. As far, as I understand, network packet parsing is already in seperate thread in your application. Applying changes can (and should) be done in separate thread too, if it is time consuming.
Pros for approach 1:
Minimized complexity
Stability
By restricting access to the 'gameWorld' variable to the EDT thread, locking mechanisms are not required. Concurrent programming is complex and requires the programmer(s) to be vigilant throughout the source base when accessing objects shared amongst threads. It is possible for
a programmer to forget to synchronize in certain instances, leading to compromised game states or program failure.
Pros for approach 2:
Scalability
Performance
Minimizing the processing done on the EDT thread ensures that the games interface and display will remain responsive to the user. Approach 1 may work for now, but later revisions of your game will not be able to scale to a more advanced interface if the EDT thread is busy doing non-ui processing.
Not the second one. You want to have as little as possible running in the EDT. If you are waiting for a lock in the EDT, it's as bad as running all the other code (on the other side of the lock) directly in the EDT since the EDT has to wait for everything else to finish.
Also, it seems that your whole game is running on the EDT. That's bad practice. You should split your code using the model-view-controller pattern. I understand your game is small and can run in the EDT, but you should probably not get into the habit.
You should have your game logic running from a timer thread (java.util.concurrent.ScheduledThreadPoolExecutor) and at the end of every period you "send" your data to the EDT and repaint with invokeLater.
You should also have some separate thread that reads the socket and that thread should write to objects that share locks with the objects you are using in the timer game thread.
My suggestion is as follows
push all loaded data from different users (thread) to a queue
use another thread to read from that queue and update UI from EDT
It should avoid your concurrency issue. How it can be achived
runMethodOfInputThread() {
while(takingInput) {
data = receiveAndInterpretIncomingPacket(); // blocks
blockingQueue.add(data);
}
}
runMethodOfUPdateUIThread() {
while(updatingUI) {
data = blockingQueue.take();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
gameWorld.updateWithNewGameInfo(data);
}
});
}
}
I have a queue of tasks that need to be performed, and a pool of workers that pick up the tasks and perform them. There's also a "manager" class that keeps track of the worker, allows the user to stop or restart them, reports on their progress, etc. Each worker does something like this:
public void doWork() {
checkArguments();
performCalculation();
saveResultsToDatabase();
performAnotherCalculation();
saveResultsToDatabase();
performYetAnotherCalculation();
saveResultsToDatabase();
}
In this case, "database" does not necessarily refer to an Oracle database. That's certainly one of the options, but the results could also be saved on disk, in Amazon SimpleDB, etc.
So far, so good. However, sometimes the performCalculation() code locks up intermittently, due to a variety of factors, but mostly due to a poor implementation of networking code in a bunch of third-party libraries (f.ex. Socket.read() never returns). This is bad, obviously, because the task is now stuck forever, and the worker is now dead.
What I'd like to do is wrap that entire doWork() method in some sort of a timeout, and, if the timeout expires, give the task to someone else.
How can I do that, though ? Let's say the original worker is stuck in the "performCalculation()" method. I then give the task to some other worker, who completes it, and then the original worker decides to wake up and save its intermediate results to the database... thus corrupting perfectly valid data. Is there some general pattern I can use to avoid this ?
I can see a couple of solutions, but most of them will require some serious refactoring of all the business-logic code, from the ground up... which is probably the right thing to do philosophically, but is simply not something I have time for.
Have you tried using a Future? They are useful for running a task and waiting for it to complete, using a timeout etc. For example:
private Runnable performCalc = new Runnable() {
public void run() {
performCalculation();
}
}
public void doWork() {
try {
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.submit(performCalc).get(); // Timeouts can be used here.
executor.submit(anotherCalc).get();
} catch(InterruptedException e) {
// Asked to stop. Rollback out transactions.
} catch(OtherExceptions here) {
}
}
If performCalculation stuck on blocking IO, there is little you can do to interrupt it. One solution is to close the underlying socket or set timeout on socket operations using Socket.setSoTimeout, but you have to own the code which reads from the socket to do that.
Otherwise you can add some reconciliation mechanism before saving the data into the database. Use some kind of timestamps to detect if the data in the database is newer that the data which original worker fetched from the network.
I suppose the easiest thing to do would be to have a separate timer thread, started when the thread with performCalculation() starts. The timer thread can wake up after a period of time and Thread.interrupt() the calculation thread, which can then perform any necessary rollback when handling the InterruptedException.
Granted, this is bolting on additional complexity to manage other problems, and consequently isn't the most elegant solution.
So, I'm working on a game engine, and I've made pretty good progress. However, my engine is single-threaded, and the advantages of splitting updating and rendering into separate threads sounds like a very good idea.
How should I do this? Single threaded game engines are (conceptually) very easy to make, you have a loop where you update -> render -> sleep -> repeat. However, I can't think of a good way to break updating and rendering apart, especially if I change their update rates (say I go through the update loop 25x a second, and have 60fps for rendering) - what if I begin updating halfway through a render loop, or vice versa?
Place your update logic in some kind of Updater worker class (implementing Runnable), and put renderer into separate worker class. When you need to update data, let Updater put that update into queue shared by both Updater and Producer. Most convenient would be to use queue which already have built-in multi-threaded support, like subclass of BlockingQueue. For example code, see javadoc for BlockingQueue.
Using queue is natural if you need to render all changes, even obsolete ones. If you wish to render only the latest change, use ConcurrentHashMap instead of queue.
Don't forget to make your updates immutable objects, so there's no chance update can change while you render it.
As Nirmal pointed out, you could use some kind of thread pool to limit number of threads and to simplify starting/stopping of threads. Refer to Executor interface and Executors utility class in JDK to see available options here.
I would suggest going pipeline with this architecture, meaning that the render stage will render all the elements updated on the previous frame, it would go like this:
Update 0
Update 1 Render 0
Update 2 Render 1
Update 3 Render 2
....
it would mean that your game will use more memory and all the objects will have to have per frame states / data
if you introduce more layers in this pipeline your game will suffer from input lag (meaning the user will see his action on the screen later then normal), so I suggest to using just this 2 stage pipeline
create pojo for every category, one runnable object contains data like fps rate, UI screen class n all requited information, you can make common information singleton, so at every time rendering start thread for updating, i recommend threadpool to keep memory consumption limited
Also note that your draw thread should never run faster then your update thread. Since if your update thread is not done with the current step yet, you will draw the same thing as before. While doing this you might miss the finishing of the update step, which in the end causes lower than optimal framerate.
(Remember drawing the exact same picture as before doesn't benefit anyone).
I've made my program using three threads (though more could be used).
Update logic (Does the data collecting and pre-processing)
Helper thread (Calculates time consuming cache pre calculations etc. at infinite sleep 1ms loop ... So this thread does not care where Update logic is going, or how fast. It just checks where it is going and calculates iF it needs to cache new items)
Render thread (Does ONLY rendering, everything it needs to render is pre-processed so it does only draw functions and calculates screen positions)
Doing this is super easy if you just have "thread safe" items you are drawing. But in game, I personally think that it is not bad thing if you render player 1 one tick ahead than player 2... Because you still want to draw as fast you can on games. Game logic thread makes sure there is no logical exceptions... So usually I think it does not matter what you draw and when, you just do it as fast as you can without thinking any "synchronizations".
I presonally prefer public static volatile item to share data between threads. And AtomicIntegerArray is a useful class for that too.
I would say add a field that specifies the thread needed to run and render, and number the threads, if the thread number == the thread required, then it is allowed to run and render, and increment the required thread field, until it hits max, then loop back to 0. Alternatively, you could, use one thread for tick and another for render, this might be easier. Here is an example code:
public Game() {
this.tickThread=new Thread(this::tickLoop());
this.renderThread=new Thread(this::renderLoop());
}
public void tickLoop() {
//code for timing...
while(running) {
//more code for timing...
tick();
}
}
public void renderLoop() {
//code for timing or syncing frames...
while(running) {
//more code for timing...
render();
}
}
Alternatively, you could say:
|MyRunnable.java|
public interface MyRunnable
{
public abstract void run(boolean toRender);
}
|MyThread.java|
public class MyThread extends Thread
{
private boolean isRender;
private MyRunnable runnable
public MyThread(boolean isRender,MyRunnable runnable)
{
this.isRender=isRender;
this.runnable=runnable;
}
public void run()
{
this.runnable.run(this.isRender);
}
}
|Game.java|
public class Game extends /*JPanel/Canvas/JFrame/Some other component*/
{
private MyThread tickThread;
private MyThread renderThread;
private boolean running;
public Game()
{
super();
tickThread=new MyThread(this::run);
renderThread=new MyThread(this::run);
//other constructor code
}
public void tick()
{
//tick code here
}
public void render()
{
//render code here
}
public void run(boolean isRender)
{
//timing variables
while(running)
{
//timing code
if(isRender)
{
this.render();
}
else
{
this.tick();
}
}
}
}