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.
Related
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.)
I have two threads in my data model layer that run in "parallel" and both compute some values. I have an mvc pattern setup so my data model has two arrays, each responsible for the values generated from each of my threads. How can i tell my view that my arrays have new data without blocking on the main UI?
My threads are running on a timer ever x seconds and generate one integer each. Each of these needs to be added to an array and, when added, the view should get a notification via the observer pattern to update the screen according to the two arrays' updated values. This should happen without ever blocking on the main ui thread. So i cant really do while(true) or set a futureValue for each thread as that would make my ui wait until the threads are done. What can i do?
You will always:
Extend the array class that contains the results and overwrite the add method
Put in the add at the end the code to inform UI-Thread
To synchronize the updates, you can use a ExecutorService with just one Thread, that you get with Executors.newSingleThreadExecutor(). In that you submit() the code to inform UI-Thread.
Your execution should be part of a WorkerThread and be handled in doInBackground
In the done() method you update the User interface (done() is executed on Swing's event dispatch thread)
See here for more information on Threads and Swing
This seems like a pretty complex approach. Here is mine:
Create a blocking queue
Get rid of the arrays and have each thread put their results in the queue
Start a worker thread that waits for items in the queue
Use SwingUtilities.invokeLater() in the worker thread to update the UI.
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.
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
I am trying to implement a GUI in java but I am beginner in swing. I want to make something clear. I read that in order to keep the GUI responsive I should use the SwingWorker class to do the task in a separate thread. Ok so far.
No I have a model with around 15 methods that are remote methods. Each method returns different object type as a result than the others.
In my view the user presses a button and the appropriate method in the model is called. Without using the swingworker the GUI froze. My question is, am I supposed to create 15 subclasses of Swingworker threads and create a NEW instance of each as needed according to user's actions? Is my understanding correct? Is there a standard way for this or what I say is a correct approach?
Thanks!
Have a look at this: Simple Background Tasks.
It seems you have two concerns. Firstly, regarding the amount of code required when using SwingWorker: you do need to create a subclass of SwingWorker for each action, but that doesn't mean they need to be top-level, named classes, or in their own files. They can be anonymous classes, as shown in the article, so that the code is within your GUI's event-handling code.
Secondly, regarding instantiation of SwingWorker objects: you can't reuse a SwingWorker, but since the jobs are being executed as a result of user activity (e.g. clicking a button), you shouldn't encounter any performance problems with instantiating new objects each time.
By all means, SwingWorkers get the job done. In my experience, I haven't liked using the SwingWorkers for just one little job. I prefer to spawn off a thread, and have that thread ask the EventDispatch thread to update the GUI. Only the EventDispatch thread should update the UI, though there are a few exceptions.
I would suggest reading about threads in threads in Swing.
Though threading can get heavy, and maybe this solution would not work for you in all cases, if a seperate thread needs to spark a change in GUI, use something like,
java.awt.EventQueue.invokeLater(new Runnable()
{
public void run()
{
// this codes runs on the event dispatch thread
// update the ui here.
}
});