Thread.sleep interrupts the code [duplicate] - java

I im creating a simple testing app that runs a check every hour on the selected directory/s using thread.sleep() through JFileChooser. But when i select the directory and the method runs the ui panel goes grey and the swing bits disappear. The thread seems to be putting the ui to sleep as well as the method its calling.
if (option == JFileChooser.APPROVE_OPTION) {
selectedDirectory = chooser.getSelectedFiles();
try {
while (true) {
runCheck(selectedDirectory);
Thread.sleep(1000*5);//1000 is 1 second
}
} catch (InterruptedException e1) {
Thread.currentThread().interrupt();
e1.printStackTrace();
}
}
Im looking for a way around this issue so that i can print the results of the checks being run in the ui .setText(result)

You are correct about the code putting the UI to sleep. Since sleep is called on the Event Dispatch Thread (the thread responsible for running the gui) the UI stops processing events and 'goes to sleep'.
I think what you want is a javax.swing.Timer.
Timer t = new Timer(1000 * 5, new ActionListener() {
public void actionPerformed(ActionEvent e) {
// do your reoccuring task
}
});
This will cause your reoccurring task to be performed off of the EDT, and thus it wont leave your ui unresponsive.

If the code you have posted runs on the EventDispatchThread, then there is no way Swing can redraw the GUI. You're blocking (sleeping in) the thread that's supposed to handle that!

This is because you are running you check in the main GUI thread and are using an infinite loop. This check is a background task and should be executed in it's own thread so that the GUI can still receive and react to input by the user.
You also do not need to write your own implementation, Java has a Timer object.
Edit: There is also a Swing specific Timer object. This will have the action occur in the GUI thread, so if your task is long, it can cause the GUI to still lock up while the action is occurring (but not while it is waiting).

Related

Creating Wait message in Java For when thread finishes [duplicate]

I have simple Java Swing application which uses zip4j to encrypt and unpack zip file. It's done by this part of code:
ZipFile zipFile = new ZipFile("dataStorage.zip");
zipFile.setPassword(password);
zipFile.setRunInThread(true);
ProgressMonitor progressMonitor = zipFile.getProgressMonitor();
if (!verify(zipFile)) {
JOptionPane.showMessageDialog(null, "You have entered incorrect password!", "ERROR", 0);
return;
}
zipFile.extractAll("./"); //runs in new thread
//After entering this while GUI freezes
while (progressMonitor.getState() == ProgressMonitor.STATE_BUSY) {
System.out.print("."); // this works normally...
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
//
}
pbEncryptionProgress.setValue(progressMonitor.getPercentDone()); //this is not updating progress bar, but getPercentDone is returning correct data
}
Problem is that progress bar is not being updated. Application GUI seems frozen. However, dots are being printed to console. How can I fix it to update that progress bar?
Please read Concurrency in Swing.
What you are doing is using up all resources of the EDT by sleeping and updating, not leaving any time for it to actually redraw your GUI. The EDT is meant for small operations on the GUI. You should never call Thread.sleep() on the EDT.
What you could do is make a Timer that would run your check every second until the check passes. That way the EDT would be free to not freeze.
A much better way of doing this is by using a SwingWorker. It has methods that do your specific thing:
A task to do in the background (In your case - unzip)
A method to publish a partial result to the GUI (in your case % done)
A method to react to partial results (In your case - update progress)
A method to invoke when done (Not shown in your case, but useful anyway).
Wrap the call pbEncryptionProgress.setValue(progressMonitor.getPercentDone()); in SwingUtilities.invokeAndWait
You shouldn#t do your zipping on the event dispacher thread (which is where all your event-handling takes place). Create a SwingWorker or someething like it to offload your heavy duty on a separate processing thread that can then inform the progress bar that can be updated on the EDT. With your solution all updates to the progress bar can only be processed when the EDT is free again, that is after your zip-operation is finished.

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/

SWT Threading: GUI not responding even after calling thread.stop()

say i have this code inside a SWT button :
Button btn = new Button(shell, SWT.NONE);
btn.addSelectionListener(new SelectionAdapter() {
//... some code...
Thread t = new Thread(){
public void run()
{
//some function that includes **INFINITE LOOP** in that
//sends a lot of UDP packets.
}
};
Display.getDefault().asyncExec(t);
try{
Thread.sleep(5*1000);}
catch(Exception e1)
{
e1.printStackTrace();
}
t.stop();
System.out.println("message");
//and some more code...
when i run this program , approximately after 5 sec it does display in the console message
but then the GUI stops responding, and when i look in the task manager, i see that my cpu (i7-4700mq) isn't fully loaded - all other apps are running just fine. Not only that, i can see that the thread is still running - via Wireshark (or task manager) i can see that the udp packets are still being sent.
i need to use t.stop() because i don't have any other threads in my program, and i dont what to make the thread itself to know when to stop (by changing some parameter value) because that will reduce performance, which is extremely important in this case.
so here are my questions:
1. why isn't my GUI responding like all other apps? isn't Display.getDefault().asyncExec(t); make the t thread run in parallel to the main(GUI) thread?
2. If i shouldn't use t.stop(), but can't stop the thread internally, because of performance, how should i stop it?
asyncExec runs it in a GUI thread. Moreover, it executes Runnable. So it just calls run method of your Thread t. t is not even started, so calling stop on it does not change anything. So what actually happens is that you run an infinite loop in a GUI thread. Of course it stops responding.

Thread.sleep putting to sleep all active threads [duplicate]

I im creating a simple testing app that runs a check every hour on the selected directory/s using thread.sleep() through JFileChooser. But when i select the directory and the method runs the ui panel goes grey and the swing bits disappear. The thread seems to be putting the ui to sleep as well as the method its calling.
if (option == JFileChooser.APPROVE_OPTION) {
selectedDirectory = chooser.getSelectedFiles();
try {
while (true) {
runCheck(selectedDirectory);
Thread.sleep(1000*5);//1000 is 1 second
}
} catch (InterruptedException e1) {
Thread.currentThread().interrupt();
e1.printStackTrace();
}
}
Im looking for a way around this issue so that i can print the results of the checks being run in the ui .setText(result)
You are correct about the code putting the UI to sleep. Since sleep is called on the Event Dispatch Thread (the thread responsible for running the gui) the UI stops processing events and 'goes to sleep'.
I think what you want is a javax.swing.Timer.
Timer t = new Timer(1000 * 5, new ActionListener() {
public void actionPerformed(ActionEvent e) {
// do your reoccuring task
}
});
This will cause your reoccurring task to be performed off of the EDT, and thus it wont leave your ui unresponsive.
If the code you have posted runs on the EventDispatchThread, then there is no way Swing can redraw the GUI. You're blocking (sleeping in) the thread that's supposed to handle that!
This is because you are running you check in the main GUI thread and are using an infinite loop. This check is a background task and should be executed in it's own thread so that the GUI can still receive and react to input by the user.
You also do not need to write your own implementation, Java has a Timer object.
Edit: There is also a Swing specific Timer object. This will have the action occur in the GUI thread, so if your task is long, it can cause the GUI to still lock up while the action is occurring (but not while it is waiting).

Java, using wait and notify properly to pause thread execution from another thread

I have an issue trying to pause a threads execution from another thread. I have read the java docs and a few stack-overflow examples and still seem to be a little lost.
Many cases are just like mine; I have a gui that spawns a thread to do some work so it can stay responsive to the user. At some point the user does something that makes it desirable to just stop the worker thread before it executes its next statement. And then after sometime, continue its work.
I have read the wait and notify documentation for Threads, and this seems to be the short answer to the question above(?).
And from what my IDE (netbeans) tells me, I must call wait and notify inside a synchronized block.
So here is what I had in my JFrame for when my start pause button was pressed. automator is my Thread object that I want paused. Its declared as static final in my JFrame. firstRunDone is just a flag for the first time the m_jbStartPause is pressed, so the automator can be started and not notified.
OnStartPauseButton()
{
synchronized(automator)
{
if(!running)
{
this.m_jbStartPause.setText("Pause");
running = true;
if(firstRunDone)
automator.notify();
else
automator.start();
firstRunDone = true;
}
else
{
this.m_jbStartPause.setText("Start");
running = false;
try { automator.wait(); } catch (InterruptedException ex) {}
}
}
}
My problem is with when I first try to pause the thread. I can hit start and the automator starts, but when I hit pause all that happens is the JFrame freezes and the automator continues doing its work.
Am i using syncronized wrong? Does automator need any handling code?
you'd better use SwingUtilities.invokeLater in order to update UI instead of using your worker thread
if you need to 'cancel' your thread, you need to make your "running" flag as volatile
instead of using "synchronized", I'd suggest to use ReentrantLock and it's conditions
FOllowing line is the issue
try { automator.wait(); } catch (InterruptedException ex) {}
This will cause the thread (YOUR GUI) thread to wait not the automator. JAVA docs says
wait()..Causes the current thread to wait until another thread invokes
the notify() method or the notifyAll() method for this object, or some
other thread interrupts the current thread, or a certain amount of
real time has elapsed
That's why your JFrame appears to be frozen and automator keeps running. You need to build a mechanism in automator that polls the status of a flag to see if it needs to continue its work..and your GUI thread should change the status of the flag to stop automator from working.
.

Categories