I'm creating a game modification that uses MySQL to get and store player data. It refreshes it's client data from the database every 4 seconds, but because it is blocking, it freezes about a second as it gets the data.
Is there any simple way to execute the command async?
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(() -> {
//Your jdbc call here
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
// Here, we can safely update the GUI
// because we'll be called from the
// event dispatch thread
MW.append(foo);
}
});
});
If you are not doing so already, use Threads. Override the run() method for things you want to run asynchronously in Java.
Also just making sure, you wait until the server returns the database data before performing another request right?
Related
I want to append some log strings to a textArea in my vaadin app.
VaadinSqlApplication.logger.info("Export start");
logTextArea.setValue("Export Start");
...
logTextArea.setValue("Export done");
but the textArea only changed after the whole function ended.
Is there any function like in JavaFX :
Platform.runLater(new Runnable() {
#Override
public void run() {
//change text
});
or in swing :
EventQueue.invokeLater(changer);
You need to enable "push" on the Vaadin UI, as by default all updates to the UI will be grouped and sent as a single response (like you say: when the function returns).
Have a look at this page, it explains the whole setup very nicely:
https://vaadin.com/docs/v8/framework/advanced/advanced-push.html
BTW, once push is enabled, you will need a similar technique as the SwingUtilities.invokeLater that you mentioned:
Making changes to a UI object from another thread and pushing them to
the browser requires locking the user session when accessing the UI.
Otherwise, the UI update done from another thread could conflict with
a regular event-driven update and cause either data corruption or
deadlocks. Because of this, you may only access an UI using the
access() method, which locks the session to prevent conflicts. It
takes a Runnable which it executes as its parameter.
For example:
ui.access(new Runnable() {
#Override
public void run() {
...
}
});
Pardon my ignorance if this is a basic question.
I want to understand how can I return control from a module and start processing in background?
Lets start component A calls component B. Component B does some basic processing, starts a background thread and immediately returns control to A. Whenever background thread completes its processing it is going to store the result in a persistence store. Whole processing by this background thread is time consuming and A cannot wait until background thread finishes off.
Component A {
Http Call component B
}
Component B {
// Got request from component A
start background thread();
return; // don't wait till background thread finishes off
}
background thread() {
// time consuming task
}
How can I achieve this behavior in java? I don't think it is entirely asynchronous form of processing since communication is happening over http connection that has timeout settings.
Update:
Component A:
Receives Http call
Component B:
Approach1:
Runnable runnable = new MyThread();
new Thread(runnable).start();
Approach2:
ExecutorService exec = Executors.newSingleThreadExecutor();
exec.execute(new MyThread());
exec.shutdown();
Both of the above mentioned approaches helped me to start background processing and return immediate control to A.
Use threads at a raw level is good solution for some easy proof of concepts, but I strongly suggest at least try to use the concurrent API from java, you can find the documentation here. and a good tutorial is here
The simplest approach is to create a Callable object that contains the instruction you want to execute in background.
Callable myInstructions = new Callable<ObjectToReturn>() {
public ObjectToReturncall() {
return object.methodCall();
}}
Using the ExecutorService submit this callable to expect a Future object.
Future<ObjectToReturn> future = executor.submit(myInstructions);
//Do anything else as this wont be blocked ..
Future API have a set of method to ask if the task is already completed.
if(future.isDone()) // Ask if the task is done
ObjectToReturn solution = future.get() // Get the result
Very simple to use the Future API .
EDIT
If you dont expect any response from the Future api, just do an operation you could use
Future<Void> future = executor.submit(new Callable<Void>() {
public Void call() throws Exception {
testA.abc();
return null;
}
});
Other option if you dont want to receive a result or get a response, just fire a thread will be
ExecutorService executor = Executors.newFixedThreadPool(5);`
executor.execute(new RunnableClass());
Also avoid call shutdown on ExecutorService , do that just until the end of the process, when you dont have more time to do, in spring or container fwks the container is in charge of shutdown the ExecutorService once the app has been shutdown
The easiest way would probably be to create a new java Thread with the background processing logic as parameter.
void componentB() {
new Thread(new Runnable() {
#Override
public void run() {
// Time consuming task.
}
}).start();
// The method continues without stopping.
}
In later versions of java, you can also use the ForkJoinPool-class to achieve this:
public class Main {
private final ExecutorService executor = new ForkJoinPool();
void componentA() {
componentB();
}
void componentB() {
executor.execute(this::timeConsumingTask);
// The method continues without stopping.
}
private void timeConsumingTask() {
// Time consuming task.
}
}
Assuming you want the HTTP call to return before the background processing is complete, your pseudocode is perfectly valid for Java.
At the next level of detail, check out the Javadoc for Thread, Runnable, and the java.nio library classes.
Is there a way to do non-blocking actions on the java interface of Berkeley DB and get the status and result of the action using a Future or something similar (like getting a result of a Callable using a Future)?
I don't want the thread calling the DB to be blocked until the DB action is done.
from what I have seen in the API documentation, Berkeley DB JE does not have an asynchronous API. every call to the DB will block the calling thread until the action is done.
Yes, you can do it, as with any DB or resource, by simply creating a thread and starting it.
Runnable r = new Runnable() {
public void run() {
// call the DB
// call your callback to run other tasks after with the result
}
};
new Thread(r).start();
That's the standard way, in Java, to do asynchronous actions. You're in charge of the threads, contrary to javascript to which you seem to refer.
I have two linux machines. On one machine I'm using a thread which starts up an executable and another internal thread reads the data from the executable and populates the database with the values from the executable, I'm using myBatis to persist the data. Later it continuously checks if the process and the internal thread is up and running. On the other machine I have the database connected remotely which is continuously deployed every night, due to this the database is being dropped and recreated. So as the database table is not available during this build an exception:
org.apache.ibatis.exceptions.PersistenceException
### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:
Table 'updates_table' doesn't exist
is thrown. Then the thread which is continuously checking for the process and internal thread is killed and it stops checking.
Can anyone help me how to handle the thread from not being killed and once the db is available and running it should try to repopulate the table. when the db is not available it should always keep trying until the db is available.
Thank you.
Consider switching to a system where you submit jobs to an Executor from the thread pulling stuff off of the process:
public class MyThread extends Thread {
private final InputStream processStream;
private final Executor executor = Executors.newSingleThreadExecutor();
public MyThread(InputStream processStream) {
this.processStream = processStream;
}
#Override
public void run() {
while ([processStream has stuff]) {
final Object obj = // Get your object from the stream
executor.execute(new Runnable() {
#Override
public void run() {
// Do database stuff with obj
}
});
}
}
private static Object getSomethingFromStream(InputStream stream) {
// return something off the stream
}
}
If an exception is thrown by your Runnable, it will be logged, but it won't be stopped, and it will just continue to the next job in the queue. Also note that this is using a single-threaded executor, so everything submitted will be executed one at a time, and in the order they're submitted. If you want concurrent execution, use Executors.newFixedThreadPool(int) or Executors.newCachedThreadPool(). Note that this answers how to keep your thread alive. If you want to resubmit a runnable for re-execution if the job fails, change its run method to:
#Override
public void run() {
try {
// Do database stuff with obj
} catch (PeristenceException ex) {
// Try again
executor.execute(this);
}
}
You can add logic to this to tailor when it will try again on an exception.
At high level, you can use Observable pattern (built in JDK) so that your code is notified during the maintenance. You can re-establish the connection back by spawning a new thread.
Use this construct :
try{
// code to update db
}
catch(MySQLSyntaxErrorException exception){
// handle db exception
}
inside your thread that runs to work with the db.
I have a simple client-server program. In one thread GUI is running, when I click "connect" button on GUI, I connect to server in new thread, after some time I receive some data from server and I want to pass it to GUI - how can I do that?
Pass a reference to your GUI object to the reading thread, and have the reading thread invoke a method of the GUI instance when he has received the data.
If the GUI is a Swing GUI, you'll need to wrap the call into SwingUtilities.invokeLater():
Thread readingThread = new MyReadingThread(gui);
readingThread.start();
and in the reading thread:
String data = readData();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
gui.dataHasBeenReceived(data);
}
});
Note that SwingWorker is designed specifically for this kind of use-case.
Generally - by passing a callback object to the new thread, and whenever you have results, invoke that callback, which in turn updates the GUI.
The "callback" can be an object implementing a custom interface of yours, that takes the result as argument.
BackgroundThread background = new BackgroundThread();
backgroundThread.setCallback(new Foo() {
public void updateGUI(Bar bar) {
//...
}
}
Than, when you have the information available in the background thread, you can just call:
getCallback().updateGUI(bar);