Im going through concurrency documentation and I can't quite understand what they mean with:
In an applet, the GUI-creation task must be launched from the init method using invokeAndWait; otherwise, init may return before the GUI is created, which may cause problems for a web browser launching an applet. In any other kind of program, scheduling the GUI-creation task is usually the last thing the initial thread does, so it doesn't matter whether it uses invokeLater or invokeAndWait.'
-What is the problem with the init being returned before GUI-creation?
-Why is the GUI-creation usually the last thing a thread does?
Tasks on the event dispatch thread must finish quickly; if they don't, unhandled events back up and the user interface becomes unresponsive.'
-How can you make it finish faster?
http://docs.oracle.com/javase/tutorial/uiswing/examples/components/TumbleItemProject/src/components/TumbleItem.java
-Where is the EDT in the above example?
SwingWorker worker = new SwingWorker<ImageIcon[], Void>() {
#Override
public ImageIcon[] doInBackground() {
final ImageIcon[] innerImgs = new ImageIcon[nimgs];
for (int i = 0; i < nimgs; i++) {
innerImgs[i] = loadImage(i+1);
}
return innerImgs;
}
#Override
public void done() {
//Remove the "Loading images" label.
animator.removeAll();
loopslot = -1;
try {
imgs = get();
} catch (InterruptedException ignore) {}
catch (java.util.concurrent.ExecutionException e) {
String why = null;
Throwable cause = e.getCause();
if (cause != null) {
why = cause.getMessage();
} else {
why = e.getMessage();
}
System.err.println("Error retrieving file: " + why);
}
}
};
-Why is initialisation of 'worker' here followed by the overwriting of several methods instead of just ';'? I have never seen this kind of notation before...
-Are all methods that aren't the 'doInBackGround()' method ,executed under the event dispatch thread?
'All concrete subclasses of SwingWorker implement doInBackground; implementation of done is optional.'
-In the code example ,I don't see a subclass for SwingWorker , unless new SwingWorker <>() , counts as a subclass?
'Be careful when invoking either overload of get from the event dispatch thread; until get returns, no GUI events are being processed, and the GUI is "frozen". Don't invoke get without arguments unless you are confident that the background task is complete or close to completion.'
-How would you use get() in a non-EDT way ?
My apologies if some questions are obvious and thank you for your time!
What is the problem with the init being returned before GUI-creation? -Why is the GUI-creation usually the last thing a thread does?
It says it right there in the text. "It might cause problems for browsers". It may be because the caller of init requires the method to create a GUI and schedule it for gui messages, and if none is created the caller fails.
How can you make it finish faster?
It's not about making the threads run faster, it's rather that if you have a long-going task, do it in a background thread instead of the event (GUI) thread as to not make it freeze.
Where is the EDT in the above example?
It's nowhere.. The applet has a EDT which is used when you for instance click a button or interact with the applet in other ways. I don't really understand your question here.
Why is initialisation of 'worker' here followed by the overwriting of several methods instead of just ';'? I have never seen this kind of notation before... -Are all methods that aren't the 'doInBackGround()' method ,executed under the event dispatch thread?
It's an anonymous class declaration of the SwitchWorker class. No, the doInBackground does not execute on the EDT, it's performed in the background. done is however scheduled on the EDT. See http://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html for reference.
In the code example ,I don't see a subclass for SwingWorker , unless new SwingWorker <>() , counts as a subclass?
It does.
How would you use get() in a non-EDT way ?
As the documentation specifies:
get()
Waits if necessary for the computation to complete, and then retrieves its result.
So you should not call it until the background method completes, as to avoid freezing of the GUI.
Related
After reading Java doc plus stackoverflow's answers no this question, i came to a thought that Thread.sleep() sleeps the current thread. Okay. How do i determine what is the current thread in my case?
When this code runs for the first time, it runs in a default thread which executes the main function. Am i right? So we sleep this thread for a second to allow the others threads to do their stuff.
After the invokeLater() is called, we start running the render method from the brand new thread so when we call Thread.sleep() the second time, we interrup this new thread while the default one is running without any kind of interruption. Am i missing something here?
The last thing i don't understand is that when i test this code, by calling Thread.sleep() it interrupts the whole Swing thing: GUI, events etc. That means that everything that is not Swing related in my program should run absolutely seamlessly but seems like it's not.
private void render() {
if (bs == null) {
createBufferStrategy(3);
bs = getBufferStrategy();
}
g = bs.getDrawGraphics();
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
onRender(g);
g.dispose();
bs.show();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
EventQueue.invokeLater(() -> render());
}
Thread.sleep() sleeps the current thread [but] How do i determine what is the current thread?
You misunderstand what "current thread" means. It means the thread that called the method.
Don't think of Thread.sleep(n) as doing anything to a thread. Think of it as a method that does nothing, and then returns n milliseconds later.
When i pass a runnable into invokeLater, i'm creating another thread and use its method run to call that render method. How is that possible?
invokeLater(r) puts r onto a queue. It also creates the EDT, but only if the EDT does not already exist. So, there will never be more than one EDT. The EDT eventually will pick r off the queue and call r.run().
In your case, r is created by the lambda expression, () -> render(). Every time your render() function is run, it will queue up a new Runnable(), and the EDT will almost immediately call render() again.
When i test this code, by calling Thread.sleep() it interrupts the whole Swing thing
ALL events are handled by the EDT. When the EDT calls your render() method, it can't do anything else---it can't handle any events---until render() returns. The sleep(1000) call insures that render() will not return for at least one full second. That is one full second during which your program will be unable to respond to any user input.
Since the EDT will be calling your render() function more or less continuously, that means that the EDT will spend almost all of its time sleeping, your program will be mostly unresponsive to user input.
A static invocation of Thread.sleep...
Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers. The thread does not lose ownership of any monitors.
(bold statement underlined by me).
If you invoke it in a thread that seems to render some UI (or in general, in the main running thread), you will almost certainly see some degradation in usability.
Note that the concepts of a thread sleeping and interrupting a thread are different.
That's why you need to catch InterruptedException when invoking Thread.sleep, as the thread might be interrupted while sleeping, e.g. by another thread invoking interrupt on the sleeping thread.
Also note that a thread can interrupt itself as well, but that obviously would not happen while it's sleeping at the same time.
Also note in your case that render adds an ansynchronous invocation of itself through a new Runnable to the EventQueue recursively, which seems pretty dangerous.
The last thing i don't understand is that when i test this code, by calling Thread.sleep() it interrupts the whole Swing thing: GUI, events etc. That means that everything that is not Swing related in my program should run absolutely seamlessly but seems like it's not.
All UI events in Swing run in a single thread. Usually it is a main thread. If this thread are taken for some activity then whole UI will hang for some time. To avoid hanging do not make heavy calculation in listeners of UI controls.
Only the Swing main thread or event dispatch thread will execute the render method.
If you want that worker threads execute code you must tell them explicitly from the main thread.
SwingWorker worker = new SwingWorker<ImageIcon[], Void>() {
#Override
public ImageIcon[] doInBackground() {
final ImageIcon[] innerImgs = new ImageIcon[nimgs];
for (int i = 0; i < nimgs; i++) {
innerImgs[i] = loadImage(i+1);
}
return innerImgs;
}
#Override
public void done() {
//Remove the "Loading images" label.
animator.removeAll();
loopslot = -1;
try {
imgs = get();
} catch (InterruptedException ignore) {}
catch (java.util.concurrent.ExecutionException e) {
String why = null;
Throwable cause = e.getCause();
if (cause != null) {
why = cause.getMessage();
} else {
why = e.getMessage();
}
System.err.println("Error retrieving file: " + why);
}
}
};
For example you could span several SwingWorker and after that sleep the main thread.
I am writing a method for my android app where I make a RecyclerView invisible, and a ProgressBar visible. I then perform some logic, before resetting the two views to their original visibility state.
With just the setVisibility() call, it works as intended. However, I am also required to call Thread.sleep() to force a wait directly after performing the logic.
Initially, I have had trouble trying to call setVisibility() to begin with. It simply did nothing. I have found many questions with similar problems, but not similar enough; I was unable to find a solution specific to my problem.
Creating a new method to simply call setVisibility(), I found that this worked as intended. I started to move my logic over, line by line, until it stopped working.
As it stands, it still technically sets the visibility correctly. However, despite being several lines down from the setVisibility() calls, my Thread.sleep() seems to be forcing itself to run before setVisibility(). I believe this was my original problem; Logically, the commands after Thread.sleep() would run directly after, and effectivley undo my setVisibility() on the very next frame.
This is my method:
public void SetMainInvisible(){
mRecyclerView.setVisibility(View.INVISIBLE);
mMainProgressBar.setVisibility(View.VISIBLE);
mTrainAdapter.RefreshAll();
Log.d("TEST", "FINISHED VIS");
try {
Thread.sleep(sSleepTime);
} catch (InterruptedException exception) {
// In the nature of a simple "Thread.sleep", there is no real reason to respond
// directly to interruption. If the sleep request is interrupted, the best course
// of action to preserve user experience is to simply move on. That said, we will
// still "re-enable" the flag that tells us the thread was interrupted, in case we
// should need to clarify if there was an interruption, later on. As is, this flag
// will be reset to false as soon as the exception is thrown.
Thread.currentThread().interrupt();
}
}
From my direct observation, when it calls, my log prints "FINISHED VIS". My application then enters the Thread.sleep() stage, and waits for 3 seconds. My views then change their visibility, as directed by the very first lines. I do not have setVisibility() anywhere else in my code.
I have tried reading further on Thread.sleep, but all references suggest exactly what I have been taught; when it executes, it forces the process to "sleep" for a set period of time. It should not force the method to postpone all other logic until it returns. On the contrary, the examples at Tutorial Point provide logic and output that suggests normal operation.
I know that I should never really be calling Thread.sleep(), but it is a direct requirement of the exercise I am completing for University. Why is Thread.sleep() forcing itself to run before any other command, despite being at the end of the method?
Changing visibility (or any other layout/drawing operation) does not have any immediate, synchronous effect on your user interface. Instead, essentially just a message is posted on the UI thread's message queue to take care of the change later.
Calling sleep() on the UI thread is a no-no. You're blocking the UI thread and execution does not return to the message handler that would take care of the relayout/redraw messages waiting in the queue. Only after the sleep() does the execution return to the message handler.
If you need to add delays to your code, use e.g. Handler#postDelayed() to post a Runnable of your own to the UI thread's message queue to be executed after a delay.
Working off #laalto's answer, I decided to test my method in the form of an AsyncTask, before looking into Handler#postDelayed() (This is something we have not covered, and I am completely unfamiliar with it). I am happy to report that it works exactly as intended.
This might be a suitable alternative, for those that are more familiar with implementing AsyncTask.
First, I implement an inner asynchronous class as follows:
private class RefreshTimesAsyncTask extends AsyncTask<Void, Void, Void> {
private long mSleepTime;
public RefreshTimesAsyncTask (long sleepTime) {
mSleepTime = sleepTime;
}
#Override
protected void onPreExecute() {
mMainProgressBar.setVisibility(View.VISIBLE);
mRecyclerView.setVisibility(View.GONE);
mTrainAdapter.RefreshAll();
}
#Override
protected Void doInBackground(Void... params) {
try {
Thread.sleep(mSleepTime);
} catch (InterruptedException exception) {
// ...
Thread.currentThread().interrupt();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
mMainProgressBar.setVisibility(View.GONE);
mRecyclerView.setVisibility(View.VISIBLE);
}
}
I then simply call new RefreshTimesAsyncTask(sSleepTime).execute();, rather than my previous function call of SetMainInvisible(). I also set static long sSleepTime=3000 in the variable declaration of my main class, due to the nature of being required to set this value as a static, and not being able to declare static variables in an inner class.
I need some help, I have a method which is performed when a button is clicked, this method then opens a new window that updates a variable in another class, the method then gets this variable from the class and then uses it.
The window that is loaded is blank, and it seems as if the wait() function is causing the thread to cease before the new window is loaded.
private void autoFillUsersActionPerformed(java.awt.event.ActionEvent evt) {
publicLesson pL= new publicLesson();
new dateSelect().setVisible(true);
try{
synchronized(this){
this.wait();
}
}
catch(Exception e){
}
int var= pL.getAmount();
System.out.println("var ="+var);
DefaultTableModel defaultModel = (DefaultTableModel) pupilTable.getModel();
for (int i = 0; i <= (userCountAmount - 1); i++) {
defaultModel.setValueAt(var, 5, i);
System.out.println("BeingSet");
}
}
You are blocking the Event Dispatch Thread. By not allowing the EDT to move past the wait call, no events can be processed which means nothing can be painted.
Instead of using a new window, try using a modal dialog. Modal dialogs block all access to other top level components (depending on the modality type) until they are properly disposed of.
Yes, indeed. Waiting on the event dispatch thread makes it block completely, and thus prevents any repaint to happen. So the EDT can't paint anything anymore while you're waiting.
Long-running tasks, and even more blocking tasks, should not be done in the event dispatch thread. It's not clear at all why you're using wait() here, BTW.
And catching Exception and ignoring it completely is one of the worst things you could do.
wait method is inherited from Object() and the docs state
Causes current thread to wait until another thread invokes the
notify() method or the notifyAll() method for this object. In other
words, this method behaves exactly as if it simply performs the call
wait(0).
Hence, you must give it something to wait for, but as you are blocking the only thread, there's no way it paints something in the meanwhile.
Is it your aim to wait in your main JFrame until the User entered the data you need in another JFrame ?
if thats your aim just have a look at Dialog ModalityTypes.
http://download.java.net/jdk7/archive/b123/docs/api/java/awt/Dialog.ModalityType.html
When constructing the new Dialog just give the parent dialog as a prameter to the constructor and then call
super(parentDialog, Dialog.ModalityType.DOCUMENT_MODAL);
then your main JFrame will wait for your new JDialog to close until it runs the rest of the function.
Hope that helps.
You cannot do that way, because Swing runs on one thread only! You need to move the processing you are doing after wait, into that window you are creating. You cannot depend on wait.
Here is a good document to read:
http://www.javapractices.com/topic/TopicAction.do?Id=153
I agree with some answers: remove the try/catch/synchronized block and use javax.swing.JDialog to receive the user input.
Refer to the official Swing documentation, it provides good enough examples,
i.e. this one http://docs.oracle.com/javase/tutorial/uiswing/components/dialog.html regarding the JDialog.
Is there a way to block the execution on the EDT, with still having a vivid gui?
I noticed that JDialog/JOptionPane has something similar, when calling setVisible(true).
Why would i need this?
My Class should satisfy to following interface:
interface Quitable {
boolean quit();
}
My Class needs a implementation like this:
class MyApp implements Quitable {
ExecutorService executor = Executors.newCachedThreadPool();
// ...
public boolean quit() {
FuturTask<Boolean> futureTask = new FutureTask<Boolean>(saveJob);
executor.execute(futureTask);
// TODO: keep gui vivid
boolean saveResult = futureTask.get();
return saveResult;
}
// ...
}
I need to return the result of the save process (which may take some time and may fail). Or would you suggest another solution? Thanks for any ideas. ;)
Dialog causes the an event loop to be executed whilst it is blocking. There is a filter that allows certain events through such as repaint requests, invocation events and events to the dialog window. The API for this is not exposed.
There was a library (Foxtrot, IIRC), that used a hack on Dialog to expose this behaviour.
I would strongly suggest structuring your program in such a way that this is not required. It's a very procedural rather than event-driven organisation. So queue your task on another thread (possible a thread pool/executor service or GUI-like event-loop), and then update the GUI with java.awt.EventQueue.invokeLater.
JDialog does not block the execution of EDT, EDT ignores events except jDialog's event when it is opened as modal.
I do suggest you to show progressbar as modal, before calling quit method.
I am using an API in a Java library which is called from the event dispatch thread and requires me to return a fully-initialized UI component. It looks like this:
public JDialog createDialog();
But I can only populate the dialog after loading from a database, which can take 10 seconds sometimes. Normally I would do that in a background thread but since this method is called from the EDT and since I have to return the dialog, that won't work. It's a third-party library so I can't change the method, but is there anything I can do to avoid blocking the EDT?
"Initialized" is not necessarily the same thing as "Populated". "Initialized" usually means that the object has been fully constructed, but may not have any data. "Populated" of course means that the data is present and any data-fetching tasks are complete. So it is possible to give your third-party library a fully initialized JDialog without any data at all.
The way I always like to solve this problem is to create a custom JDialog which displays a busy message or a progress bar or the like, and then request the data in another thread. When the data is returned, I replace the busy message with the data(On the EDT!). As to how you should perform your request in a background thread, I recommend using SwingWorkers. I like to use a private SwingWorker inside my custom JDialog which handles the request in the doInBackground() method, and handles the Display-related tasks in the done() method. Doing it this way will ensure that display-related tasks only occur on the EDT, and database-related tasks only occur OFF the EDT. If you'd like a reasonably good introduction to using SwingWorkers, check out Sun's tutorial on worker threads. A simple example would be:
public class DBDIalog extends JDialog{
private JLabel busyLabel = new JLabel("Fetching data from DataBase");
public DBDialog(){
//do your initialization stuff here
}
private class DBFetcher extends SwingWorker<Void,DBInfo>{
#Override
protected DBInfo doInBackground() throws Exception{
return fetchDataFromDB(); //or whatever database call to make
}
#Override
protected void done(){
try{
DBInfo info = get();
//replace your busy label with your DBInfo
}catch(InterruptedException e){
//do appropriate thread interrupted stuff
}catch(ExecutionException e){
//do appropriate general error handling stuff
}
}
}
}
A few things to remember, though: the done() method is NOT abstract, so you aren't required to override it. You should, though. If your doInBackground() implementation throws an exception, that exception will be swallowed unless done() has been overridden. Also, don't make changes to your GUI from inside the doInBackground(), unless you use SwingUtilities.invokeLater(Runnable), as doInBackground() is executed from a different thread than the EDT and making GUI changes from a background thread is asking for strange and inexplicable bugs.
When should this be used? Unlike other programming tasks, the point at which something takes too long to respond is a lot shorter in GUIs--The number I've usually seen written down is about 250ms. If your task takes longer than that, it should be in a background thread. In your case, 10 seconds should definitely be in a background thread, but then you already knew that :)
EDIT:
Seeing your comment, I see that most of my post is pretty moot. However, you can still use a SwingWorker:
Have your SwingWorker perform the data-retrieval, and in the done() method, have it construct the JDialog from the data and hand that dialog to your third-party library.
Construct the dialog without data, and then start a task to populate it.
From a user-experience perspective, anything that takes 10 seconds from initiation to completion is going to be an issue. It's best if you should them something right away, even if it's not in final form. If necessary, you could pop a modal dialog that simply says "Loading."