Java: how to use JTableModel in eventQueue - java

I have a class extending AbstractTableModel and it pools Data from a Database, Since its a Swing Component I initialize it in EventQueue, the Problem is most of the operation such as getting Connection and Querying DB all runs in eventqueue hence it takes time to load the JTable. Is there a way to separate the two processes.

Use a SwingWorker for doing the heavy background tasks to avoid blocking the EDT.

If you need to do a time-consuming operation, to prevent the GUI from freezing you have to do it in a thread different than the Event Dispatcher Thread. Those threads are called Worker threads, an example on how to use them is detailed in this other question.
Edit: I have found a very nice introduction and example article here.

You can set up the table in a thread separate from the event queue like this:
new Thread() {
public void run() {
// setup the table
}
}.start();
This will result in the code in run being run in a new thread, which is what you want.

Related

Multi-threading with Swing

I am trying to write a multi-thread program with Swing. Essentially how the program works is that when it runs it will have a robot(represented by a circle in screenshot) that is wondering around in a field. This robot should be controlled by a thread of it's own. The program has a button "Launch Robot" that will create another robot on the field(upto a max of say 10). Right now I have the basics of the program, but it all runs under one thread. I can launch as many robots as I want but they all run under a single thread. But I want that whenever I click "launch Robot" an independent thread be created and control that robot. This is how the program looks right now:
The UML diagram for the program is as following:
Since its a bit long I won't post the whole program. But the method that starts and updates the robots(currently controlling only one robot on the field) is as follows:
public void gameStart(){
Thread gameThread = new Thread(){
public void run(){
while(true){
//execute one time step for the game
gameUpdate();
//refresh screen
repaint();
//give other threads time
try{
Thread.sleep(1000/UPDATE_RATE);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
};
gameThread.start();
}
My question is how can I achieve multi-threading for such a scenario? I know the basics of SwingWorker, but since I haven't done any multi-threading, I have no idea on how to make several threads work and be updated by one thread(update position of robots that are controlled by threads).
EDIT: Just to make my point, this is a project that I am working on. It's not about if multi-threading makes sense in this scenario or not.
Create a RobotModel that contains a Collection<Robot> and defines their interaction. Iterate the model in the doInBackground() implementation of a SwingWorker. Invoke publish() as meaningful events arise, and process() updates to the RobotWorld view by querying the model. As discussed here, there should be no drawing in the model and no interaction logic in the view. A single worker should suffice for a moderately complex model, but you can synchronize multiple workers as shown here.
A good option to achieve this is to use ScheduledThreadPoolExecutor.
Instantiate the thread pool via:
ScheduledThreadPoolExecutor threadsPool = new ScheduledThreadPoolExecutor(size);
To create a new Robot Thread, use:
threadsPool.submit(new Runnable() {
#Override
public void run() {
launchRobot();
}
});
This way, each invocation will instantiate a new Thread.
You can set the limit of the total number of allowed Thread via the "size" argument.
You can also pass a result after each thread completes using:
public <T> Future<T> submit(Runnable task, T result)
If you want less detail, you could let Java do the work for you with the following convenience API:
Executors.newCachedThreadPool() (unbounded thread pool, with automatic thread reclamation) or:
Executors.newFixedThreadPool(int) (fixed size thread pool)
Remember us, Executor. Remember what was done here today. And may Adun watch over you
This robot should be controlled by a thread of it's own.
Why?
IMO, the most important way to describe any thread is to say what it waits for. In an internet server, an accept thread waits for incoming connections from new clients, and a client thread waits for additional commands from a single client. In a program that performs massive parallel computations, a worker thread waits for tasks to be performed. In a GUI program, the event dispatch thread waits for keyboard and mouse events. Etc., etc.
What will your robot thread wait for?
If it waits for time to pass (i.e., if it calls Thread.sleep()), then your GUI framework probably already has a timer thread that does that, and you might want to consider using it. (In Swing, you would use the javax.swing.Timer class to submit new timed tasks.)

How to utilize SwingWorker and/or Timer?

I have been working on a program and am currently trying to resolve an issue. The program's purpose is to read through records from a database, pull information upon a certain trigger, and then display that information the GUI. The problem here is getting that data from the database to appear in the GUI, allow for some time for it to be represented on the screen, and then do the same for the next one and loop through.
I can get the data and put it on screen in the GUI, but my problem lies within allowing for that pause.
I have tried Thread.sleep but I have read that it is discouraged to do so.
What seems to be recommended is utilizing SwingWorker and/or Timer. I have spent a good amount of time studying these two but I am having difficulty fully understanding it and being able to apply it to my program. Given my problem and my program's purpose, can anyone help explain the significance of SwingWorker and Timer?
Timer executes in the EDT and the SwingWorker makes work in another threads. I really like this example Swing Worker example
Note that the Swing timer's task is performed in the event dispatch
thread. This means that the task can safely manipulate components, but
it also means that the task should execute quickly. If the task might
take a while to execute, then consider using a SwingWorker instead of
or in addition to the timer.
Caveats:
All interactions with the UI, updates, creates, should be done from within the context of the Event Dispatching Thread.
javax.swing.Timer
The Swing Timer is a special timer that allows you to setup a periodical callback that is guaranteed to execute within the context of the EDT
SwingWorker
SwingWorker is solution desinged to make a UI developers life easier by providing the mechanisms for running code in the background while providing easy (at least easier) mechanisms for synchronizing updates to the UI within the EDT.
For your problem, I would recommend the use of the SwingWorker, as you can pause in the background without effecting the UI's responsiveness
SwingWorker worker = new SwingWorker<Object, Object> {
public void doInBackground() throws Exception {
while (!loadingDone) {
Object data = loadMoreData();
publish(data);
}
// This only matter if you actually care about the result
// of what has being processed here...
return null;
}
public void process(List<Object> chunks) {
// Now in the UI...
}
}
Check out...
SwingWorker JavaDocs
Worker Threads and SwingWorker
For more details...

How to implement a thread to my home-made desktop application

I have build a desktop application that connected to database, the function is add-delete-modify. I make it separate to 3 JInternalFrame.
The problem now is, when I execute bulk update to update >500 orders, my application will hang but it is processing the request. Then I will run this application again, so now I have 2 windows opened with same application. After the 1st application is done for the job, I can use my previous application again.
Now my question is, how to implement thread to my app so that I can run as many function in same window application?
Long-running tasks (like your bulk update) must not be done in the event dispatch thread (the thread where all the GUI operations are made), else, as you observed, the GUI freezes.
Use SwingWorker to execute your long-running tasks in a background thread. Its javadoc has a useful example, and its also described in the Swing tutorial.
Multi Threading in java now is very simple with the addition of [java.util.concurrent.][1]
What you need to do is
split the 500 job orders into smaller batches, say 10 per batch.
Create a threadpool with a configured number of threads, say 10 threads.
Create a Runnable/callable task which will pick up these batches from a common place and do the CRUD operations on the DB.
You will additionally need a common data structure which will have the results of these CRUD operations. So once the Runnable/callable task finishes it's operation, it updates this data structure with the result of the operation
Also keep in mind that the access to these data structures
- the one that holds the batch of job orders
- the one that holds the result of operations
should be synchronized.
For thread pool you can use one of the
Executors.newFixedThreadPool or Executors.newCachedThreadPool()
Take a look at Swing Threads.
Especially at:
SwingUtilities.invokeLater()
What you should do is to seperate your UI class from your Database Access and Modifications class. You can then, from your UI you can then call something like this:
new Thread(new Runnable()
{
public void run()
{
//Call database stuff here
}
}).start();
Note however, that having a lot of database operations going on at the same time can cause errors especially since the database might lock tables to which it is currently reading/writing to. What I suggest is that you keep it to one operation at a time and use threads to display a marquee progress bar or something similar.
i'd just use:
new Thread(new Runnable()
{
public void run()
{
//Things to do in new thread...
}
}).start();
Or if you want to use that often, you can make class that implements Runnable, so you dont have to rewrite everything in run() function.

Starting Thread after GUI construction

I have a program that builds the GUI in the constructor. I need a Thread separate from the EDT to run immediately after the object in question is constructed. Could anyone point me in the right direction?
I need a Thread separate from the EDT
Threads are separate from the EDT so all you do is create a Runnable and then start it.
You only have to worry if the Thread updates any GUI components. If this is the case then you may want to use a SwingWorker. Read the section from the Swing tutorial on Concurrency for more information.
What you want to use is a SwingWorker<T,V>. In the doInBackground method, open the connection and start fetching data. When you have enough data to update the gui, call the publish method. Implement the process method to update the gui with the new data from publish, and finally, implement the done method to notify the user when you're finished fetching data.
The Swing Worker is a generic, so when you construct it you need to provide two types: T and V. V is the type for the data passed between publish and process methods and T is the type returned by doInBackground and passed to done.
build your GUI an open a new window inside a new Runnable invoked called by: SwingUtilities.invokeLater
you have two choises
1) wrap Thread into Runnable as demonstrated here
2) I am not very satisfy with plain SwingExecutor, then I use for that Executor and SwingWorker, monitored by PropertyChangeListener, example here,
please carrefully with number of threads started by Executor. Executor doesn't care if SwingWorker ends or not and there still exists Bug where is pretty possible to overload maximum (somewhere in API) simultaneous jobs live by Executor in same time.
by this reason is there possible implements PropertyChangeListener

Updating Swing component from another thread with invokeLater or SwingWorker

I'm developing a small app, which would have Swing GUI. App is doing IO task in another thread, when that thread finishes GUI should be updated acordingly to reflect thread's operation result. Class running in a (worker, non-GUI) has object passed to it in contructor which would be used for updating GUI, so I don't need to put GUI stuff in a non-GUI class, but rather pass object for updating GUI to that class.
As I understand form reading here, (thread/swing) safe options for updating (changing) Swing GUI would be to use javax.swing.SwingUtilities.invokeLater(), javax.swing.SwingUtilities.invokeLaterWait() and/or javax.swing.SwingWorker() which basically are doing the same thing.
This all threading issue with Swing is a little confusing for me, and yet I need to use threads to do anything meaningful in GUI apps and not hung GUI while processing in EDT, so what interests me for now is this:
Are invokeLater and invokeLaterWait like sending message to EDT and waiting for it do it when it finishes processing messages that were before that call?
is it correct from Swing thread safety aspect, to do something like this:
interface IUPDATEGUI {
public void update();
}
// in EDT/where I can access components directly
class UpdateJList implements IUPDATEGUI {
public void update() {
// update JList...
someJList.revalidate();
someJList.repain();
}
}
class FileOperations implements Runnable {
private IUPDATEGUI upObj;
List<File> result = new ArrayList<File>; // upObject is accessing this
public void FileOperations(IUPDATEGUI upObj) {
this.upObj = upObj;
}
private void someIOTask() {
// ...
// IO processing finished, result is in "result"
}
public void run() {
someIOTask();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
upObj.update(); // access result and update JList
}
}; );
}
}
In case this isn't correct then how should this be done?
If I could, I would prefer to use invokeLater instead of SwingWorker if possible, because I wouldn't need to change my whole class and it's somehow more neat/distinct me (like sending a message in Win32 apps).
Thanks in advance.
Using invokeLater() and invokeAndWait() passes the Runnable parameter into the queue awaiting execution in the EDT. So calling invokeLater() will cause the Runnable to execute in the EDT when the EDT is able to process the request. invokeAndWait() simply waits (in the calling thread) until this execution takes place.
Using SwingWorker is ideal if you want to do background tasks that notify the EDT either at the end of execution or in intermediate states. An example would be to pass the current progress of a process to a JProgressBar.
For your example it seems that SwingWorker is a better choice but if you don't want to change your code too much then calling invokeLater() when the process is done will be just fine.
I'd recommend not using the invokeAndWait until java 7. I found a spurious wake-up on this method that can cause really painful bugs. For me it led to some really rare and hard to debug null pointer exceptions.
http://bugs.sun.com/view_bug.do?bug_id=6852111
It's fixed as of java 7 b77.
invokeLater is fine. This puts the call into the AWT event queue, so that it will get executed in the EDT in due course. Your program will continue running, and does not wait for your callable to get called.

Categories