Maintaining Synchronization using JAVA and JNI - java

I have been struggling to accomplish a GUI driven task that is initiated in a thread that takes a while to compute and is also accomplished over the JNI using C++ native code. When the computationally intensive task is run, the synchronization is lost, otherwise, synchronization is fine.
Can someone help with an implementation structure where synchronization of the time is not lost? I have a hunch it is because my use of JNI.
The structure of the my problem is below:
1) A button (animate) is selected and triggers an event for a GUI listener
2) GUI recognized that the button was pressed and starts a thread below:
3) Once button is pressed again, the thread closes.
private class Animator implements Runnable
{
public void start()
{
if (thread == null)
{
thread = new Thread(this, "Animator");
thread.start();
}
}
public void run()
{
while (animate.isSelected())
{
updateAnimations();
}
resetAnimations();
thread = null;
}
public void updateAnimations()
{
double time = scene.getTime(); // A singleton class and scene time
time += 10;
scene.update(time); // the scene updates its parameters to time and redraws the GUI. One of the computations is done over the JNI and takes too long and synchronization is lost (i.e. time = [10 40 80 ...])
}
Thread thread;
}

Related

JavaFX buttons don't disable

I have a task that can take a few seconds to a few minutes, and when I click on the button to execute the task, it runs the task but does not always disable button A and enable button B.
Here is the code that I am using:
#FXML
public void onExecute(ActionEvent event){
btnExecute.setDisable(true);
btnStopExec.setDisable(false);
new Thread(){
#Override
public void run(){
Platform.runLater(() -> {
QueryTable qt = new QueryTable(currentMysqlConn, currentDatabase);
qt.setTabPane(resultsTabPane);
qt.setQuery(queries);
qt.executeQueries();
btnExecute.setDisable(false);
btnStopExec.setDisable(true);
});
}
}.start();
}
If I comment out the button disabling in Platform.runLater() button A gets disabled and button B get enabled, but after Platform.runLater() runs. Why does this work sometimes and not others?
According to the Javadocs for Platform.runLater(...), it
Runs the specified Runnable on the FX Application Thread
So the only thing your background thread does is to schedule all your time-consuming database work to run on the FX Application Thread: your background thread is basically redundant, and your UI will be unresponsive while the database work is running.
If it happens that a frame is rendered between the calls to btnExecute.setDisable(true); and the runnable you define getting executed, then you will see the disabled state change. If not, then all your code gets executed during the same frame rendering(*), so you will never see the disabled state change.
Platform.runLater() should be called from a background thread just to update the UI. So you could make this work as follows:
#FXML
public void onExecute(){
btnExecute.setDisable(true);
btnStopExec.setDisable(false);
new Thread(){
#Override
public void run(){
QueryTable qt = new QueryTable(currentMysqlConn, currentDatabase);
qt.setTabPane(resultsTabPane);
qt.setQuery(queries);
qt.executeQueries();
Platform.runLater(() -> {
btnExecute.setDisable(false);
btnStopExec.setDisable(true);
});
}
}.start();
}
Platform.runLater(...) is a pretty low-level approach for FX work. The javafx.concurrent package defines a higher-level API for this: in particular the Task class encapsulates a background task and provides callbacks that will be executed on the FX Application Thread so you can update the UI. The Javadocs have copious examples, but you could do:
#FXML
public void onExecute(){
btnExecute.setDisable(true);
btnStopExec.setDisable(false);
Task<Void> databaseTask = new Task<Void>() {
#Override
public void call(){
QueryTable qt = new QueryTable(currentMysqlConn, currentDatabase);
qt.setTabPane(resultsTabPane);
qt.setQuery(queries);
qt.executeQueries();
return null ;
}
};
databaseTask.setOnSucceeded( event -> {
btnExecute.setDisable(false);
btnStopExec.setDisable(true);
});
new Thread(databaseTask).start();
}
(*) This is a somewhat imprecise statement, but it's qualitatively correct. Technically, the rendering thread blocks while actions are being executed on the FX Application Thread. (The two are not the same thread, but they have a large amount of synchronization between them.) Thus it's impossible for a frame to be rendered between the call to QueryTable qt = new QueryTable(...); and btnStopExec.setDisable(true);. It is possible for a frame to be rendered between btnStopExec.setDisable(false); and the execution of your runnable (i.e before QueryTable qt = new QueryTable(...);). If such a frame is rendered, you see the disabled state change; if not, you don't. Whether or not that happens is just down to the timing of the calls with respect to the "pulses" (frame renderings), which are targeted to happen every 1/60th second.

Applets - init(), EDT and threads

Java is not my mother tongue and I've been fighting with this problem for a little while.
Basically, I am finding a behavioural difference between calling method switchApplets() directly from init(), and calling it from within a new thread spawned by init().
The consequence of calling it from inside the new thread is that the new applet whitescreens -- until/unless the user resizes or minimizes their browser. If called at the end of init(), the new UI renders immediately without any input from the user. But that's not an option because it doesn't wait for the thread to finish its prep work.
Trimmed-down code:
public class PreLoader extends Applet implements AppletStub {
static JProgressBar pBar = null;
static JLabel message;
public void switchApplets() {
try {
Class main_class = Class.forName("MainClass");
Applet main_applet = (Applet)main_class.newInstance();
removeAll();
setSize(0,0);
setLayout(new GridLayout(1,0));
add(main_applet);
main_applet.init();
main_applet.start();
main_applet.setStub(this);
}
catch (Exception e) {
}
}
public void init() {
pBar = new JProgressBar(0, 100);
pBar.setValue(0);
pBar.setStringPainted(true);
message = new JLabel("Beginning work!");
add(message);
add(pBar);
FlowLayout flow = new FlowLayout();
setLayout(flow);
Thread t = new Thread ( new Runnable () {
public void run ()
{
longRunningFunction1();
longRunningFunction2();
message.setText("Work complete! Stand by..");
switchApplets(); //does NOT work as intended from here
return;
}
} );
t.start();
//switchApplets(); //works as intended if called HERE
}
public void longRunningFunction1() {
//perform some tasks, advance progress bar
}
public void longRunningFunction2() {
//perform some tasks, advance progress bar
}
public void start() {
return;
}
public void appletResize(int width, int height) {
return;
}
}
I tried making init() wait for the thread to finish so that I could call switchApplets() from there, but that only blocked the EDT and prevented the UI from updating. Also tried playing with SwingUtilities' invokeLater/invokeAndWait, but even though switchApplets() gets run on the EDT, it seems that it MUST be called directly from init() (or at least the thread init is running on) to have the desired effect.
Why does calling switchApplets() from within a new thread result in a slightly different (and unwanted) UI behaviour?
The consequence of calling it from inside the new thread is that the new applet whitescreens -- until/unless the user resizes or minimizes their browser.
It's likely a deadlock caused by trying to do UI code on the wrong thread.
I tried making init() wait for the thread to finish so that I could call switchApplets() from there, but that only blocked the EDT and prevented the UI from updating.
You're on the right track. You need to call switchApplets() only from the EDT, and only after the work is done on the other thread.
Are you sure you tried using invokeLater() or invokeAndWait() from within the spawned thread after the long running functions were done? It's been a long while since I did applets but I'm not aware of any applet-specific reason why it wouldn't work, and it would work in any other case. I.e.,
public void run()
{
longRunningFunction1();
longRunningFunction2();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
message.setText("Work complete! Stand by..");
switchApplets();
}
});
}
However, the most proper way to do this is with a SwingWorker rather than a manually created thread. SwingWorker (which is not nearly as well-known as it should be) is designed exactly for the goal of performing background tasks on a separate thread while still being able to update the GUI with progress updates and the results. E.g.,
new SwingWorker<Void,Void>() {
#Override
protected Void doInBackground() { // is called on a background thread
longRunningFunction1();
longRunningFunction2();
return null;
}
#Override
protected void done() { // is called on the Swing thread
message.setText("Work complete! Stand by..");
switchApplets();
}
}.execute();
The Void stuff is because SwingWorker is also capable of returning results and sending intermediate progress updates, but this example doesn't use those features.
You indicated that your long running functions are also updating a progress bar. That's another thing that should happen only on the Swing thread. In practice you can often get away without it, but it's dodgy. Your progress updates can use one of the SwingUtilities.invoke methods, or the mechanisms of SwingWorker; either should work. (SwingWorker itself provides two different ways to do it: Call addPropertyChangeListener (Swing thread) and setProgress (background thread), or call publish (background thread) and override process (Swing thread).)
Also, a small suggestion: if it's inconvenient to deal with a checked exception (or impossible to usefully do so), rather than catching and ignoring it, you should at least catch & rethrow it as an unchecked exception:
catch (Exception e) {
throw new RuntimeException(e);
}
That way, the stacktrace and error message of any exception will not be lost.

JTextArea text disappears

I'm making a chess program for a project. I'm trying to add a move history box to the side of the board. The move history works fine, and the data is properly sent to the text area, but the text inside the JTextArea disappears while the AI is thinking about his move.
public void aiMove(){
if (!playing){ return; }
paintImmediately(0,0,totalX,totalY);
ai = eve.getMove(chess,wtm,aiOut); //text disappears here
chess.makeMove(ai);
wtm = !wtm;
humanMove = true;
writeMove(ai); //updates move history, text reappears here
playing = stillPlaying();
repaint();
}
private void writeMove(Move move){
char c = "abcdefgh".charAt(7-move.fromY);
char h ="abcdefgh".charAt(7-move.toY);
String s = Character.toString(c)+(move.fromX+1)+" - "+Character.toString(h)+(move.toX+1)+" ";
if (!wtm){
String q = chess.getFullMove()+". "+s+" ";
moves.setText(moves.getText()+q);
}
else {
moves.setText(moves.getText()+s+"\n");
}
}
Here's a print screen of what's happening.
http://s13.postimage.org/mh7hltfk7/JText_Area_disappear.png
SOLVED
Thanks to all replies. I changed aiMove() so it creates a thread. Here is what I did.
Attempt #3... swing is still so foreign to me. I didn't want to change writeMove to getMove or I would have to rewrite the human's turn slightly. Since the project is essentially done, I am trying to avoid as much work as possible :)
The GUI is entirely optional anyways, I was just doing it for fun, and to try and learn a bit of swing.
public void aiMove(){
if (!playing){ return; }
if (!aiThread.isAlive()){
aiThread = new Thread(){
public void run(){
ai = eve.getMove(chess,wtm,aiOut);
chess.makeMove(ai);
wtm = !wtm;
humanMove = true;
SwingUtilities.invokeLater(new Runnable(){
public void run(){
writeMove(ai);
}
});
repaint();
playing = stillPlaying();
}
};
aiThread.start();
}
}
It also fixed a problem I had before, in that if I were to hold down the 'a' key (force ai move), it would queue up many forced ai moves. Now that doesn't happen.
The problem is your AI thinking is CPU intensive/time consuming, thus it is considered a long running task. You should not do long running tasks on GUI Event Dispatch Thread as this will cause the UI to seem frozen and thus only show updates after the task has finished.
Fortunately there are 2 different approaches you could use:
Use a Swing Worker which as the tutorial states:
The SwingWorker subclass can define a method, done, which is
automatically invoked on the event dispatch thread when the background
task is finished.
SwingWorker implements java.util.concurrent.Future.
This interface allows the background task to provide a return value to
the other thread. Other methods in this interface allow cancellation
of the background task and discovering whether the background task has
finished or been cancelled.
The background task can provide
intermediate results by invoking SwingWorker.publish, causing
SwingWorker.process to be invoked from the event dispatch thread.
The background task can define bound properties. Changes to these
properties trigger events, causing event-handling methods to be
invoked on the event dispatch thread.
Alternatively create separate Thread for AI thinking and wrap setText call in SwingUtilities.invokeLater(...);
Thread t=new Thread(new Runnable() {
#Override
public void run() {
}
});
t.start();
UPDATE
After reading MadProgrammers comment (+1 to it) please remember to create/manipulate your GUI/Swing components on EDT via the SwingUtilities.invokeLater(..) block. You can read more on it here.
UPDATE 2:
That edit is defeating the point, the only call on EDT in SwingUtilitites block should be the setText or atleast only code that manipulates a Swing component i.e
public void aiMove(){
if (!playing){ return; }
if (!aiThread.isAlive()){ //originally initialized by constructor
aiThread = new Thread(){
public void run(){
ai = eve.getMove(chess,wtm,aiOut);
chess.makeMove(ai);
wtm = !wtm;
humanMove = true;
SwingUtilities.invokeLater(new Runnable(){
public void run(){
writeMove(ai);
}
});
repaint();
playing = stillPlaying();
}
};
aiThread.start();
}
}

Platform.runLater and Task in JavaFX

I have been doing some research on this but I am still VERY confused to say the least.
Can anyone give me a concrete example of when to use Task and when to use Platform.runLater(Runnable);? What exactly is the difference? Is there a golden rule to when to use any of these?
Also correct me if I'm wrong but aren't these two "Objects" a way of creating another thread inside the main thread in a GUI (used for updating the GUI)?
Use Platform.runLater(...) for quick and simple operations and Task for complex and big operations .
Use case for Platform.runLater(...)
Use case for Task: Task Example in Ensemble App
Example: Why Can't we use Platform.runLater(...) for long calculations (Taken from below reference).
Problem: Background thread which just counts from 0 to 1 million and update progress bar in UI.
Code using Platform.runLater(...):
final ProgressBar bar = new ProgressBar();
new Thread(new Runnable() {
#Override public void run() {
for (int i = 1; i <= 1000000; i++) {
final int counter = i;
Platform.runLater(new Runnable() {
#Override public void run() {
bar.setProgress(counter / 1000000.0);
}
});
}
}).start();
This is a hideous hunk of code, a crime against nature (and
programming in general). First, you’ll lose brain cells just looking
at this double nesting of Runnables. Second, it is going to swamp the
event queue with little Runnables — a million of them in fact.
Clearly, we needed some API to make it easier to write background
workers which then communicate back with the UI.
Code using Task :
Task task = new Task<Void>() {
#Override public Void call() {
static final int max = 1000000;
for (int i = 1; i <= max; i++) {
updateProgress(i, max);
}
return null;
}
};
ProgressBar bar = new ProgressBar();
bar.progressProperty().bind(task.progressProperty());
new Thread(task).start();
it suffers from none of the flaws exhibited in the previous code
Reference :
Worker Threading in JavaFX 2.0
Platform.runLater: If you need to update a GUI component from a non-GUI thread, you can use that to put your update in a queue and it will be handled by the GUI thread as soon as possible.
Task implements the Worker interface which is used when you need to run a long task outside the GUI thread (to avoid freezing your application) but still need to interact with the GUI at some stage.
If you are familiar with Swing, the former is equivalent to SwingUtilities.invokeLater and the latter to the concept of SwingWorker.
The javadoc of Task gives many examples which should clarify how they can be used. You can also refer to the tutorial on concurrency.
It can now be changed to lambda version
#Override
public void actionPerformed(ActionEvent e) {
Platform.runLater(() -> {
try {
//an event with a button maybe
System.out.println("button is clicked");
} catch (IOException | COSVisitorException ex) {
Exceptions.printStackTrace(ex);
}
});
}
One reason to use an explicite Platform.runLater() could be that you bound a property in the ui to a service (result) property. So if you update the bound service property, you have to do this via runLater():
In UI thread also known as the JavaFX Application thread:
...
listView.itemsProperty().bind(myListService.resultProperty());
...
in Service implementation (background worker):
...
Platform.runLater(() -> result.add("Element " + finalI));
...

How do you repeatedly call a Thread in Java?

I want a thread to execute in the background every 500 milliseconds. To do that, I extended a Thread, implemented ActionListener and put the class that I extended into a Timer. The Timer calls run() every 500 milliseconds. However, my whole Swing GUI freezes up when this thread is downloading stuff from the Internet. I want it to run in the background, without freezing up the GUI while it waits for IO to finish. I also the downloader to finish downloading before we wait 500 milliseconds.
gogogo() is called to initialize the whole process:
public final class Downloader extends Thread implements ActionListener
{
public static void gogogo()
{
t= new Downloader();
new Timer(500, (ActionListener) t).start();
}
public void run()
{
doStuff(); //the code that i want repeatedly called
}
public void actionPerformed(ActionEvent e)
{
run();
}
}
Just start the thread once, make it loop, and do Thread.sleep(500L) with each iteration. That probably makes more sense that starting a brand new thread every 500ms. No reason to incur the associated cost if you can avoid it.
Instead of using the swing timer try using the java util timer or the ScheduledExecutorService. the swing timers share a pre-existing timer thread and that may be causing the freezing.
A recommendation from the java tutorial:
In general, we recommend using Swing timers rather than general-purpose timers for GUI-related tasks because Swing timers all share the same, pre-existing timer thread and the GUI-related task automatically executes on the event-dispatch thread. However, you might use a general-purpose timer if you don't plan on touching the GUI from the timer, or need to perform lengthy processing
If your GUI is freezing up, then your lengthly task (doStuff) is probably running on the Event Dispatching Thread. While it hogs that thread, other actions can't use it.
If you're trying to run a task repeatedly, you may be better off with the TimerTask class
public class Downloader extends TimerTask {
public void run() {
doStuff();
}
}
... elsewhere ...
Timer myTimer = new Timer();
public void gogogo() {
myTimer.scheduleAtFixedRate(new Downloader(), 0, 500);
}
That's a little different in that your task will be scheduled to run every 500 ms rather than with a 500 ms delay. When you're done, just use myTimer.cancel() to stop the repeating task execution.
You need to start the thread on each timer action. Calling the thread's run() method does not start the thread.
public void actionPerformed(ActionEvent e)
{
//run();
Downloader t = new Downloader();
t.start();
}
Might be better to use an anonymous class for the actionlistener. Excuse my java syntax but I have not verified it...
new Timer(500,
new ActionListener(){
public void actionPerformed(ActionEvent e)
{
//run();
Downloader t = new Downloader();
t.start();
}
}).start();
Or without the timer...
public static void gogogo()
{
t= new Downloader();
t.start();
}
public void run()
{
while(true){
doStuff(); //the code that i want repeatedly called
Thread.sleep(500);
}
}
Hmm, most likely all you need to do is reduce the thread priority, so it doesn't eat all your resources.

Categories

Resources