How to use the Semaphore in Java - java

I have a function that takes a while and want to display a waiting screen :
Loading.showSplash("Working...");
for (FileListRow row : model.getList()) {
performAction(row);
}
Loading.hideSplash();
The problem is that the performAction(row); seems to be executed before the loading screen and hence it defeat the purpose.
Any help on solving this to force the waiting screen to show before the rest is executed and to force the function to finish before the waiting screen goes away.

Can I assume this is a Swing program?
If yes, then it looks like you're performing your long-running operations on the event dispatch thread. This is a bad idea; you should perform all long-running operations on a workert hread. See the Java tutorial for more information.
And if you do perform long-running operations on a background thread, your definitely do not want to use a semaphore to suspend the GUI thread until those operations complete -- or even until they start. The GUI thread should be allowed to run freely and dispatch events, or your UI will have "lags," which are annoying to users. As other posters have indicated, your worker thread can use SwingUtilities.invokeLater() to update the UI.

Try giving this a shot. You should call all code that does GUI updates from the Event Dispatch Thread (EDT). Swing is not thread safe.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Loading.showSplash("Working...");
}
});
new Thread(new Runnable(){
public void run(){
for (FileListRow row : model.getList())
{
performAction(row);
}
}
}).start();
Loading.hideSplash();

I'll assume you are developing a Swing application.
Read the javadoc of the SwingWorker class : http://download.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html.
The idea is to
1. display your splash screen
2. start a thread which performs all your actions in the background.
3. when the background operations are finished, hide the splash screen
The SwingWorker takes care of this. Note however that the background operations may not use any Swing-related component or class, since they're not thread-safe and must execute in the event dispatch thread (EDT).
Another, simpler approach would be to display your splash screen, and then use SwingUtilities.invokeLater to perform your operations and hide the splash screen. This way, everything will be done on the EDT, but the splash screen will be displayed before the other operations are performed. Note however that with this technique, the application GUI will be unresponsive until the splash screen is hidden.

Related

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/

When may we need to use runOnUiThread in android application?

I have a code sample that uses this function to run a thread runOnUiThread. why and when may we need to use it?
edit
What about to use AsyncTask class, what's the pros and cons??
You have to use runOnUiThread() when you want to update your UI from a Non-UI Thread. For eg- If you want to update your UI from a background Thread. You can also use Handler for the same thing.
From the Docs -
Runs the specified action on the UI thread. If the current thread is
the UI thread, then the action is executed immediately. If the current
thread is not the UI thread, the action is posted to the event queue
of the UI thread.
Syntax -
Activity_Name.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// your stuff to update the UI
}
});
Update -
AsyncTask -
If you want to do some Network operation or anything that blocks
your UI in that case AsyncTask is best options. There are several
other ways for performing the same Background Operations as you can
use Service, IntentService also for doing Background Operations.
Using AsyncTask will help you doing your UI work and also won't block
your UI until your background Operation is going on.
From the Docs -
AsyncTask enables proper and easy use of the UI thread. This class
allows to perform background operations and publish results on the UI
thread without having to manipulate threads and/or handlers.
To update userinterface from thread you need to use runOnUiThread. But using asynctask is better than using runonuithread. android-runonuithread-vs-asynctask this link can help you

Multithreading and UI behavior

I have a java app in which I use a thread. My thread runs every 20 seconds but, when it runs it kind of blocks the UI ... i. e. whenever the thread is running and the user clicks on button on anything on UI it doesnt respond sometimes.
Could anyone tell me a solution to this problem.
in java Swing, any change made to the state of the UI should be done in a single pre-existing thread called the EDT (event-dispatcher thread).
if that's not the case, you typically experience weird glitches / freezes. one of the most common symptom is that part of the UI becomes gray (except since java 1.6, where the ui is still painted like before, but unresponsive).
the good way to go is to use a dedicated method to queue your changes to the UI in the EDT :
SwingUtilities.invokeLater(Runnable toRunInEDT);
note that if you call invokeLater, the runnable is executed after all currently queued event have been dispatched. that means that the next line of code could be executed before the code in the runnable. there is a synchronous version as well (which should not be executed from the EDT):
SwingUtilities.invokeAndWait(Runnable toRunInEDT);
Some additional tips, on top of what edralzar said:
You can use the convenience method SwingUtilities.isEventDispatchThread() to check if code is in fact running on the event dispatch thread. And, like edralzar said, any code that creates GUI components, modifies the state of GUI components or reads the state of GUI components should run on the Event Dispatch Thread.
Another thing to consider, however, is that code running on the EDT should be able to execute rather quickly. So you cannot just solve things by running everything on the event dispatch thread. If you do the following, your GUI will be frozen for five seconds:
SwingUtilities.invokeLater(new Runnable(){
public void run(){
try{
Thread.currentThread().sleep(5000);
}catch(InterruptedException e){
//Ignored in this example
}
}
});
Why is it frozen? Because all GUI events and GUI updates are performed on the EDT, and if the EDT sleeps for 5000 miliseconds, no GUI updates can be performed during that time.
This article might be an interesting read.
Sounds to me like the thread you're referring to (that runs every 20 seconds) is also the thread that governs the UI.
The solution is to separate the two processes onto different threads.

Execution trapped inside the button

I have a method called inside a button that run almost an infinite loop. I can't access the other buttons while running this method.
How I make to free the interface to access other buttons while running this method?
//methods inside the button
this.setCrawlingParameters();
webcrawler = MasterCrawler.getInstance();
webcrawler.resumeCrawling(); //<-- the infinite loop method
you need to use a SwingWorker
The way Swing works is that it has one main thread, the Event Dispatch Thread(EDT) that manages the UI. In the Swing documentation, you will see that it is recommended to never to long-running tasks in the EDT, because, since it manages the UI, if you do something computationally heavy your UI will freeze up. This is exactly what you are doing.
So you need to have your button invoke a SwingWorker so the hard stuff is done in another thread. Be careful not to modify UI elements from the SwingWorker; all UI code needs to be executed in the EDT.
If you click the link for SwingWorker, you will see this:
Time-consuming tasks should not be run
on the Event Dispatch Thread.
Otherwise the application becomes
unresponsive. Swing components should
be accessed on the Event Dispatch
Thread only
as well as links to examples on how to use a SwingWorker.
Start a new Thread:
// In your button:
Runnable runner = new Runnable()
{
public void run()
{
setCrawlingParameters(); // I removed the "this", you can replace with a qualified this
webcrawler = MasterCrawler.getInstance();
webcrawler.resumeCrawling(); //<-- the infinite loop method
}
}
new Thread(runner, "A name for your thread").start();

How can Swing dialogs even work?

If you open a dialog in Swing, for example a JFileChooser, it goes somewhat like this pseudocode:
swing event thread {
create dialog
add listener to dialog close event {
returnValue = somethingFromDialog
}
show dialog
(wait until it is closed)
return returnValue
}
My question is: how can this possibly work? As you can see the thread waits to return until the dialog is closed. This means the Swing event thread is blocked. Yet, one can interact with the dialog, which AFAIK requires this thread to run.
So how does that work?
The existing event dispatch thread is blocked, and so swing creates another thread that pumps the events. This is then the event dispatch thread for the duration of the dialog.
Swing creates a separate native thread for pumping native OS window messages. This is separate from the AWT event thread.
On Windows, you see these threads
"AWT-Windows" - the native UI thread
"AWT-EventQueue-0" - the current AWT event dispatch thread
EDIT: The downvote is correct. This is not true, at least not in all cases.
Modal dialogs often take care of pumping AWT events themselves. If you run the code
SwingUtilities.invokeAndWait(new Runnable()
{
public void run()
{
JOptionPane.showInputDialog("hello");
}
});
and then break, looking at the threads, you will see only one EventQueue thread. The show() method of JOptionPane pumps events itself.
Frameworks like Spin and Foxtrot take the same approach - they allow you to create a long running blocking method on the EDT, but keep the events flowing by pumping events themselves. It is possible for swing to have multiple dispatch threads (I'm sure this was the case with older versions of swing) but now that multicore is common, the concurrency issues, in particular ensuring changes on one thread are correctly published to other threads, mean that using multiple EDTs produces bugs in the current implementation. See
Multiple Swing event-dispatch threads
It's the AWT's thread, not Swing's.
Anyway, AWT runs the dispatch loop within the show. Input events to blocked windows are blocked. Repaint events, events to unblocked windows and general events are dispatched as usual.
You can see this either by adding the line:
Thread.dumpStack();
into the even handling for the modal dialog, or more easily from the command line with jstack or use ctrl-\/ctrl-break in the command window of the application.
The Foxtrot library abuses this to provide a more procedural (as opposed to event-driven) model. It's also used by WebStart/Java PlugIn to provide dialogs for JNLP services and others when called from the application EDT.

Categories