Using threads in Swing GUI in Java - java

I am using the following codes, to replace a JLabel each 0.5 seconds, with the same sentence but with another dot.
Runnable r1=new Runnable() {
#Override
public void run() {
while(true){
try {
connectionStatus.setText("Connection Established...");
Thread.sleep(500L);
connectionStatus.setText("Connection Established.");
Thread.sleep(500L);
connectionStatus.setText("Connection Established..");
Thread.sleep(500L);
} catch (InterruptedException ex) {
}
}
}
};
Thread th1=new Thread(r1);
th1.start();
Is this the real purpose from using threads? Does this affect the speed of the program? If the thing that I'm doing is so stupid, is there any other way to do such stupid things?

Is this the real purpose from using threads?
If you want these operations to run in parallel then the answer is yes
is there any other way to do such stupid things?
If you update your label at a fixed intervals then you should probably go for using Timers instead
On a side note:
You should avoid using while(true) when doing multithreading, you should either define a stop boolean that you test in the loop or use Thread.interrupted() if you extend the Thread class
When updating UI elements from non EDT thread, you should use SwingUtilities.invokeLater

There are several issues with this code.
Swing components should be accessed/updated on the Event Dispatch Thread and are not thread-safe. So starting another Thread to update your JLabel is simply not done. See the 'Concurrency in Swing' tutorial for more information
Even if you would call the code above on the EDT, you would not see any updates of the JLabel as the Thread.sleep would block the EDT, and avoiding a repaint.
So the solution is to use the javax.swing.Timer class, which allows to perform operations on the EDT at regular intervals, and does not block the EDT in between. See also the Timer tutorial. As a side effect, using timers avoids the while(true) loop which would never end.
You can find a more complete answer here.

Try using a Timer from Swing library instead. It's generally a better idea to use these for GUI-related tasks. This will especially come in handy when you try to use timed events on multiple components as all Timers share the same timer thread.
It also provides a flexible and intuitive programming model based on listeners.
No need to reinvent the wheel.
Timer tutorial
EDIT:
A little followup on the wheel reinvention part. You should also take Andrew Thompson's suggestion into consideration. There are components in Swing that have been designed specifically to indicate progress. It's unnecessary to do it using a label, as you're trying to do. Take a look at JProgressBar. It's going to be simple and it will look more professional.

First one suggestion, rather use something like this:
while(!isStopped) {
// do some work
}
With your approach you just created infinity loop.
Note: Have look at Java Timer. It's very usefull and efficient.

Try this,
You will need the above approach if your purpose is parallel processing.
You have given while (true) , which will lead to a Infinite loop, you must control it,
its better to have a boolean variable to control the nos. of iteration of the while loop.
Keep you non-ui thread processing OUT of the Event Dispatcher Thread, else you will make the GUI hang till
your thread has finished its run() method. In your case its Infinite, as while (true).
If you want to sync the non-ui work and ui work, then you can use Handler or Swing-Worker.
Last but not the least, Take a look at TimeTask, see this link
http://enos.itcollege.ee/~jpoial/docs/tutorial/essential/threads/timer.html

Related

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...

Java Swing application: how to get data from the GUI thread to another thread?

In my Java application with a Swing GUI, I would like to achieve the following.
There is a non-GUI thread running, performing some work. At one point, this thread needs input from the user before it can continue. Then, I would like to make some changes to the GUI, await a specific GUI action (like the user pressing the OK button), get the entered data from the GUI to the non-GUI thread, and let it continue with the computation.
Looking around, I have found a lot of information about how to initiate the execution of a (long running) task from the Swing GUI thread on another thread, but nothing on my problem.
SwingUtilites.invokeAndWait sounds like it does the job, but first, it takes a Runnable argument instead of a Callable, so there is no straightforward way to return a result, and second, it does not solve the problem of waiting for a certain GUI event.
I realize I could make up my own solution using e.g. a CountDownLatch, but to me, the problem seems frequent enough for there to be a standard solution.
So, my questions are: Is this really a frequent problem, and if yes, is there a solution in the standard library / libraries? If there is no standard solution, how would you solve it? If this problem doesn't occur often, why not?
Kicking off the GUI changes is easy, so I assume you're only asking about getting data back to the worker thread.
First, create a Blocking Queue. Have the worker thread call take() on the queue, and it will block. In GUI space, once the user enters valid input, put it on the queue with offer() and the worker thread will receive the data and can continue.
I think, you can use ExecutorService where you can also track progress of your task through Future interface.
java.awt.EventQueue.invokeLater works nicely for running code on the AWT EDT. Propbably best to copy mutable data or better use immutable data. Locks are possible, but a bit dicey.
If you other thread is an event dispatch loop, you could implement something like invokeLater for your thread (but don't make it static!). Probably use it behind some interface that makes sense to the behaviour of the thread - so it's real operations rather than run which is specified as doing anything it pleases. If your thread is going to block, then a BlockQueue is fine, but don't block from the AWT EDT.
java.awt.EventQueue.invokeAndWait is like using a lock. Probably you are going to use another lock. Or perhaps a lock like invokeAndWait on you own thread. If you don't, AWT uses a lock anyway. So, uncontrolled nested locks, that probably means deadlock. Don't use invokeAndWait!
final bool result = doSomething();
SwingUtilities.invokeLater( new Runnable(){
//Runnable method implementation.
//use result in your method like local var.
});
Make sure that your shared data is synchronized use lock objects.
If you need to pass arguments to Runnable just make your local variables final,
and use them in run method.

How do you use the Event Dispatch Thread?

I learned about how swing isn't thread-safe. Delving deeper, I discovered that every modification to a swing component must be done on the Event Dispatch Thread in order to prevent various issues associated with multithreading. However, the information seemed to completely stop there. There doesn't seem to be a good tutorial that explains how to do this anywhere accessible on the internet.
Patching together information from code posted in relation to other issues, it seemed that I would have to put an untidy block of code around every single swing modification in my program (like this example from my own code):
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
setTitle("Frame title");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setSize(800, 480);
setLocationRelativeTo(null);
setIconImage(Toolkit.getDefaultToolkit().createImage(ClassLoader.getSystemResource("Frame icon.png")));
}
});
} catch (Exception e) {
e.printStackTrace();
}
Basically, is this right? Do I have to put that code (or the equivalent with invokeLater) around every modification to a Swing component in my code?
Also, why doesn't Swing do this automatically?
The trick is that when swing calls you it will ALWAYS be in the EDT, so you don't have to worry about it.
However if you are in a timer or an action triggered by some other external event, your main thread or any other thread you've created then yes, you have to use invokeLater or invokeAndWait.
In other words, yes swing does do "it" automatically. Needing to use invokeXx is so rare that if swing were to do it internally it would waste too much time.
Many java programmers never figure this out and it can cause some pretty nasty hard-to-find problems with drawing your GUI. I do wish swing threw an exception when you called it not using the EDT--Java would have a better reputation when it came to professional GUIs if it did because there would be less crap out there.
note that any code executed from event handlers is already run in the EDT (the Event in the acronym)
this means that for general use (while you don't mess with swingworkers and threadpools and such) you are always inside the EDT
and you can always query if you are in the EDT with SwingUtilities.isEventDispatchThread()
also note that in your code the call to invokeAndWait will fail and throw an error when you are in the EDT already
Basically, you dont draw or update the GUI from outside of the EDT.
You use SwingUtilitis.invokeLater() from another thread to ensure the GUI drawing or updating code is run on the EDT.
Not all your UI code must be part of a runnable in an invokeLater call. That is simply because a large part of your program will be run on the EDT anyway. You need to dispatch messages to the EDT only when you are on a different thread.

Is a swingWorker guaranteed to throw a state property change event on completion?

I have a class that takes in a number of SwingWorkers and runs them one at a time in a certain order. I use a ReentrantLock to make sure that only one worker runs at a time. Normally I would always unlock in a finally clause, but I need it to stay locked until the worker completes.
nextWorker.getPropertyChangeSupport().addPropertyChangeListener("state",
new PropertyChangeListener()
{
#Override
public void propertyChange(PropertyChangeEvent evt)
{
if (evt.getNewValue().equals(SwingWorker.StateValue.DONE))
{
executionLock.unlock();
}
}
});
If this is not the case, is done() guaranteed to be called? I would prefer not to call unlock this way, as it would violate encapsulation to some degree.
Due to the nature of the project it is likely that this will come up in a code review. In that case it would be helpful to have a verifiable source. So far I have been unable to find one.
personally I tried everything possible with SwingWorker, but always ends me with done(), but I think that there no guarantee that implemented methods from Future ends correctly, still there this Bug
no idea about your code about lock/unlock another thread or process, but I suggest to use Executor for multithreading,
how to get exceptions from SwingWorker Task
personally I never ever had bad experiences with SwingWorker or some un-expected lack, but all MultiThreading Gurus told about SwingWorker for Production code never, there is still required use of Runnable#Thread instead of SwingWorker

Multithreading in a networked swing game: using invokeLater vs locks

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);
}
});
}
}

Categories