Swing: Running code immediately vs invokeLater - java

I'm currently working with a thread control class someone else wrote. It is used for a java swing application. I have two methods, but I am confused as to why I am getting different behaviors from both. From what I know and read about the event dispatcher thread and Swing, there should be no difference in the two methods below. Apparently, this is not true.
//If this is the AWT Event Processing thread then run the code immediately,
//otherwise schedule it for later processing
public static void runWithEventThread(Runnable r)
{
if (EventQueue.isDispatchThread())
{
r.run();
}
else
{
EventQueue.invokeLater(r);
}
}
//Schedule the runnable for later processing by the AWT Event Queue
public static void runLaterWithEventThread(Runnable r)
{
EventQueue.invokeLater(r);
}
When using runWithEventThread() to display popups while updating GUI (new buttons/repainting), I found that the GUI would mess up sometimes. However when using runLaterWithEventThread(), it was all fine, no issues.
Only problem is that when using runLaterWithEventThread() I found that when I had multiple popups that would be displayed one after the other (after OK clicked) all popups were displayed at once.
From what I understand, both the methods should be doing the same thing. Can someone please explain what is going on

If your first method is executed from the event thread, it MAY act differently than the second method: If there are any events currently waiting on the event thread, those events will be processed BEFORE your run() method is executed if you use the second method, but if you use the first method, your run() method will be executed immediately, and any existing events on the queue will be run AFTER your run() method finishes.

Related

How do I create methods for a thread?

I'm writing an android application.
In the main thread, it is possible to define methods and then call the methods, which helps keep the code clean. In a new thread, how does one define methods, to avoid writing all the code in "one block"? Is it possible to call methods defined in the main thread, or can you define them inside the new thread somehow?
So to be clear, what I want to do is this:
volatile Runnable feedToBuffer = new Runnable()
{
#Override
public synchronized void run()
{
if(boolean)
{
MethodA();
}
else
{
MethodB();
}
}
and not this:
volatile Runnable feedToBuffer = new Runnable()
{
#Override
public synchronized void run()
{
if(boolean)
{
//Code that was in MethodA
}
else
{
//Code that was in MethodB
}
}
}
Is that possible?
I realize this info is probably out there somewhere, but haven't found it, so really grateful for any help. :)
It's perfectly possible. Thread is just a sequence of actions, and if it involves a method call, it will be executed within that sequence. It doesn't matter.
Threads are in no way tied to the structure of your code. The main difference between the threads you start and the one you have already when the app starts is the points of entry. When Android starts the main thread, it enters your app in many points, in the activity that would be the lifecycle calls like onCreate() or button click listeners. When you create a new thread, your point of entry is the run method from where you can call anything you want.
There is also a difference in that the main thread runs an event loop. Basically, there is a queue of messages that it has to process. Each time something arrives to the queue, it processes the message, then goes back to waiting. In that sense the main thread never ends. Your thread, however, stops when it reaches the end of the run method. Of course, you can implement a similar event loop for your thread yourself.
Other than that there are no fundamental differences in how the threads operate, you can call methods from any thread freely. Of course, there are rules of multithreading like avoiding blocking the main thread, synchronization, and so on, but it's too much to cover in one answer.

Java Swing making the thread wait once

I'm trying to make my GUI wait for 2 seconds after a recent update in the graphics. It means that after I use:
boardLogo.repaint();
boardLogo.revalidate();
I want the GUI to wait before making further computations and then paint them again.
The code:
SwingUtilities.invokeLater(new Runnable() {
#SuppressWarnings("rawtypes")
#Override
public void run() {
SwingWorker swingWorkerExample = new SwingWorker(){
#Override
protected Object doInBackground() throws Exception {
return null;
}
protected void done(){
try {
Thread.sleep(2000); //wait 2 seconds.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
swingWorkerExample.execute();
}
});
//.... more code here
boardLogo.repaint();
boardLogo.revalidate();
But when I run it - first it executes the last two lines, then waits for 2 seconds...
To be honest, my knowledge about Threads and Java Swing is not the best (especially when it comes to understanding swing worker, which I've tried to read about from Oracle site), so I would appreciate it if the answer will be detailed.
Thanks!
when I run it - first it executes the last two lines, then waits for 2 seconds ... my knowledge about Threads and Java Swing is not the best.
You say, it executes the last two lines. Ever stop to wonder what it is?
It is a thread. Threads are what execute code in a Java program, and every line that gets executed is executed by some thread.
When your code calls invokeLater(), it is submitting a task (i.e., a piece of code) to be executed by Swing's event dispatch thread (EDT); and when your code calls swingWorker.execute() it is submitting a task to be performed by one of Swing's background threads.
The whole point of having more than one thread in a program is that they can be doing different things at the same time.
In your case, you've got the EDT sleeping for two seconds while, at the same time, some other thread is calling boardLogo.repaint(); and boardLogo.revalidate();
There's a couple of important things to know about Swing and multi-threading:
All of your event handlers will be run by the EDT.
An event handler should never do anything that takes more than a small fraction of a second, because your application will not be able to respond to any other events (i.e., it will appear to be "hung") until the handler returns.
No other thread is allowed to interact with any of Swing's GUI components.
One important use-case for invokeLater() is, it's how code running in the background thread can communicate with GUI components. invokeLater() submits a task (i.e., a piece of code) that will be run in the EDT.
The main use-case for SwingWorker is pretty much the opposite of that: It's how an event handler, running in the EDT, can kick off a task that is going to take more than a small fraction of a second to complete.
You can learn about this stuff by working your way through the Swing Concurrency tutorial: https://docs.oracle.com/javase/tutorial/uiswing/concurrency/

Why would you use nested InvokeLater calls in Java?

I'm refactoring some code that runs a multi-stage process. Each step is inside a nested java.awt.EventQueue.invokeLAter.... call. It looks a little like this:
import java.awt.EventQueue;
public class NestedInvokeLater {
/**
* #param args
*/
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
changeTabPanel();
copySomeFiles();
enableNextButton1();
upDateProgressBar(10);
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
readInFiles();
doSomethingToFiles();
upDateProgressBar(15);
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
doSomethingElse();
upDateProgressBar(100);
}
});
}
});
}
});
};
}
I am new enough at Java that I don't get the point of nesting these calls to add 'jobs' to the EDT, and I'm not 100% confident with fiddling with these calls either. I think I understand what the invokeLater call does, and what each step does. Please correct me if this understanding is wrong:
invokeLater is used to add some invocation to the list of jobs to be done in the Event Dispatch thread. Java then deals with when/how each invocation is done, ensuring that the EDT and in turn the GUI doesn't lock as it performs jobs 'in the background'.
Nesting these calls says to me that we should queue a set of jobs, one of which is to queue something, which will queue some jobs....one of which is to queue something. But the first inner invocation is only ever queued once the previous job is done. Everything occurs sequentially (this is in line of my understanding of the whole process), but I don't see why you would use nested requests to queue jobs to do so. I would have, if I was writing this from scratch, have simply created functions for each invocation and called them in turn.
I recognise, being only a novice at Java I am probably missing something huge that makes this nesting important. But there is no documentation of this, and no commenting in the code about the nesting.
What am I missing? What, if anything is the point in this code?
There is no point in doing so many nested invocations. It is based on a good intention, but it's badly implemented.
If you want to do this properly, use a SwingWorker.
The documentation of SwingWorker has a neat example of how you should implement performing several tasks in the background of the application (the PrimeNumbersTask class showed there).
Edit: Here's an example of what you should do with SwingWorker in your case.
class SequentialInvoker extends SwingWorker<Void, Integer> {
#Override
public void doInBackground() {
changeTabPanel();
copySomeFiles();
enableNextButton1();
setProgress(10);
readInFiles();
doSomethingToFiles();
setProgress(15);
doSomethingElse();
setProgress(100);
}
}
To actually show the progress on a progress bar, take a look at the following code, copied from the SwingWorker documentation:
JTextArea textArea = new JTextArea();
JProgressBar progressBar = new JProgressBar(0, 100);
SequentialInvoker task = new SequentialInvoker();
task.addPropertyChangeListener(
new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
progressBar.setValue((Integer)evt.getNewValue());
}
}
});
With this code, your progress bar will show the progress as the SwingWorker works.
One advantage of doing it this way is that other queued up things get to run in between. So, in between the section that does changeTabPanel() and the part that does readInFiles(), the GUI will get to respond to the user clicking on a button etc...
The actual implementation is a bit of a confusing mess and illustrates (IMHO) why anonymous functions were not such a good idea. Your inclination to make the three parts "real" functions and call them sequentially is a good one. But, to maintain the same logic, what you really need to do is make them three runnables and have each invokeLater the subsequent one.
And #Cyrille is correct that doing these major tasks on the EDT is poor practice.
There are three jobs that are used in invokeLater here. Each one does a costly thing, call updateProgressBar and then adds the next job to the EDT.
The thing is, if the code just continued to the next costly thing instead of calling invokeLater to do it, the EDT would not have the chance to repaint the progress bar to show the new value of it. This is probably why the work is broken in three invokelater calls.
Now, this is not what I would call a good code. This is pretty bad practice: one should not do a long process in the EDT because it blocks everything and makes the GUI unresponsive. This should be changed so that the process is done in a separate thread, and then only call invokeLater to update the progress bar.
Edit: To answer more generally the question in the title: there is almost never a sensible reason to nest calls to invokeLater. When you are doing this, you say "queue this job so that it is done in the same thread but later when you feel it would be good". So it gives a chance to the rest of the GUI to repaint itself, like here. But it only makes sense if you have a long running process in the EDT, which you should always avoid.
The code you posted makes absolutely no sense to me - you can just write everything sequentially because you have no parallel threads running which might post events on the EDT. You need the first invokeLater() though, as you use Swing components.
But as your code suggests you are doing some relatively lengthy operations: reading files, do something with them, ... You should run these methods in a new worker thread, NOT the EDT. And, in the run() method of these worker threads, you'll need a call to EventQueue.invokeLater() to have your GUI updated.

How to modify this example code in order to show the differences between the three methods for updating the UI in BlackBerry

I'm triying to understand the differences between the three methods for managing the UI interactions.
I'm really confused with these three terms when triying to figure them out in a real case.
The below code shows the function of the invokeAndWait method, but if I replace it by
invokeLater or getEventLock() the program will work exactly the same way.
Could someone please modify the code in order to show the differences between the three
methods for updating the UI?
public final class HelloWorldMainScreen extends MainScreen
{
private LabelField labelField;
public HelloWorldMainScreen()
{
labelField = new LabelField("Hello World");
add(labelField);
MainScreenUpdaterThread thread = new MainScreenUpdaterThread(this);
thread.start();
}
public void appendLabelText(String text){
labelField.setText(labelField.getText()+"\n"+text);
}
}
public class MainScreenUpdaterThread extends Thread {
HelloWorldMainScreen mainScreen;
public MainScreenUpdaterThread(HelloWorldMainScreen mainScreen){
this.mainScreen = mainScreen;
}
public void run(){
for (int i = 0; i < 10; i++) {
try{
Thread.sleep(5000);
}catch(InterruptedException ex){};
UiApplication.getUiApplication().invokeAndWait(new Runnable() {
public void run() {
mainScreen.appendLabelText("Update");
}
});
}
}
}
These three concepts are very confusing for many starting people so any explanatory source code
describing their functions will be strongly helpful for anybody, I think.
Thanks in advance!
My understanding for three different approaches:
Application.getEventLock() - get event lock as soon as possible
UiApplication.invokeLater() - put Runnable into event queue and it will be executed after all other tasks that were put before to this queue
UiApplication.invokeAndWait() - same as previous one except calling thread will be stopped until Runnable will be run
My personal opinion never use first method. I don't think that any of my draw or UI changes tasks are more prioritized that other tasks already put to event queue.
I use mostly second method and I used once last one when I implemented some modal popup dialog selection.
getEventLock() :Retrieves the application user interface event lock.
Worker threads should synchronize on this thread if they wish to execute code serialized with the event thread. Your worker thread should hold the lock only for a short period of time, as this action pauses the thread dispatcher.
Any operation involving the device's user interface must be done with the lock held. The UI system also guarantees that any methods it invokes will execute on a thread that already has the lock.
An application should never call notify or wait on this object.
invokeLater(): Puts runnable object into this application's event queue.
Invoke this method, passing a runnable object, to have that object's run() method invoked on the dispatch thread, after all pending events are processed.
If there is no event dispatch thread (ie. hasEventThread() returns false), then the last item to be queued is dropped when the queue surpasses its size limit. Note: If an application does not have an event thread, you may invoke setAcceptEvents(boolean) to inform the runtime system that the application no longer accepts events. All events queued to that application are then discarded.
invokeAndWait(): Puts runnable object into this application's event queue, and waits until it is processed.
Invoke this method, passing a runnable object, to have that object's run() method invoked on the dispatch thread, after all pending events are processed.
This method blocks until the insert event is processed (that is, until the runnable object's run() method returns).
It is safe to call this method on the event dispatch thread. In this case the runnable will be executed immediately.
If there is no event dispatch thread (ie. hasEventThread() returns false), then the last item to be queued is dropped when the queue surpasses its size limit. Note: If an application does not have an event thread, you may invoke setAcceptEvents(boolean) to inform the runtime system that the application no longer accepts events. All events queued to that application are then discarded.
API documentation: http://www.blackberry.com/developers/docs/4.3.0api/net/rim/device/api/system/Application.html#invokeLater(java.lang.Runnable)

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