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.
Related
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/
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).
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).
I have a Swing form with a button, which is when clicked starts SocketServer for listening to incoming requests in a separate thread. Following is structure of classes I have.
MainForm : This is my main class which launches Swing Form. It has two buttons, "start server" and "stop buttons".
MySocketServer : This class is where SocketServer object exists, it has methods startServer() and stopServer().
Following is Start button's Click Event Body.
t = new Thread(new Runnable() //Object t is created globally in this main class.
{
public void run()
{
myss = new MySocketServer(); //Object myss has similar accessibility as t.
myss.startServer();
}
});
t.start();
And Following is Stop Button's Click Event Body
myss.stopServer();
if(t.isAlive());
System.out.println("Thread is still alive!!");
Though I can toggle SockeServer "start" and "stop" as my times I want, but I realize that everytime I start the server, new thread gets created and it remains active even though server is stopped using MySocketServer's method.
I can use stop() of Thread and stop the thread execution but since it is depreciated and I have studied that threads get ended once their run() method has executed completely, but I have startServer() method separated so that it can handle connected clients separately.
Please note that startServer() has While-Listen loop, so essentially run() method of thread is in infinite state of execution, until I explicitly call stopServer() and halt the loop.
what can be done here?
Firstly, you are right to not try to use Thread.stop(). It is potentially dangerous.
So what should you do?
One possibility might to be to write your server thread like this:
....
ServerSocket ss = new ServerSocket(...);
try {
while (keepGoing) {
Socket s = ss.accept(...);
try {
// do stuff
} finally {
// close socket
}
}
} finally {
// close the server socket
}
and have stopServer clear the keepGoing flag. But the problem is that the stop typically will come while the thread is blocked in the accept call, and there's nothing to unblock it.
Another possibility might be to call Thread.interrupt() on the thread. That causes some things to unblock, and throw an exception, but I don't think it will unblock the accept() call though. (However, this is still better than setting a flag if the "do stuff" part needs interrupting.)
The real solution (I think) is to close the ServerSocket. This will cause the ss.accept() call to unblock and throw an exception, which you need to handle in the server thread.
In your MySocketServer class in the while loop you need a flag which will test if it should keep running or not.
In your newly added shutdown method set the flag which the loop in the thread will test. Once the loop breaks and run() returns the thread will end.
You shouldn't use stop(). Take a look at this http://docs.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html
The solution with infinite loop and start/stop flags is straightforward but leads to ineffective using of CPU time. The better way is to use wait/notify approach. The way you operate with MySocketServer gives me feeling that you have other infinite loop inside the startServer(). That's why you have to stop it. It would be better to wrap this loop into it's own thread internally and make start/stop methods operate with this thread state in wait/notify manner.
Forgot to mention, as your GUI runs in its own thread you can't escape start/stop flag inside the MySocketServer because using wait() in GUI thread will make it hanged.
I never gave the use of Thread.Sleep much thought, until I downloaded the latest version of Netbeans. Netbeans now warns you not to use Thread.Sleep. So I did some research on the topic and found people stating that you only need to use Thread.Sleep for debugging/testing purposes and that if you use it at any other time you have poorly written code.
So my question is how can I keep from using Thread.Sleep in the following situation.
I have written a server application that interfaces with another application. The server has two threads:
Handles the data coming over the socket and sends back other information or just plain acknoledgements.
This is the main thread. After kicking off the socket thread it going into an indefinite while loop. Within this while loop I check to make sure the socket thread is still active and that the user hasn't asked to exit the application via a TrayIcon interface. Then I sleep and continue this while loop.
With this application, the TrayIcon is the only UI.
Here is the snippet I'm referencing:
// continues running as long as the exitth file is not present and
// the tray icon is not in a safe to exit status.
while(doNotExit())
{
if (getPrimaryThread() == null || !getPrimaryThread().isAlive())
resetsThreadAndSocket();
try
{
// check to see if the socket threads are still active, if not create new ones.
if ((getPrimaryThread() == null || !getPrimaryThread().isAlive()))
createSocketThread();
// check right before sleeping that the user does not want to exit.
if(getTrayIcon().isExiting())
break;
// puts the main Thread to sleep for 3 seconds
Thread.sleep(3000);
}
catch(SQLException ex)
{
_log.error(ex.getMessage(), ex);
restartDatabase();
}
}
The 'preferred' method in most cases would be to use the ScheduledExecutorService built into JavaSE for performing a periodic task, rather than reimplementing it yourself every time using a while loop and Thread.Sleep().
There's nothing wrong per-se with your example. The language just now has a much more robust support for doing that built into it as of Java 5.
Instead of your Thread.sleep(3000) do:
getPrimaryThread().join(3000)
This will wait for the thread to exit for 3 seconds.
You should consider attaching an event listener to your tray icon instead of polling its state. That way you won't need an extra thread just for monitoring.
If you can't do that for some reason, you can still do away with the extra thread as the Timer class can do the waiting for you.
You seem to be paranoid that some condition (maybe a RuntimeException or Error?) is going to cause your socket Thread to just die. Ideally, you would design your Socket Thread such that it protected itself from crashing. The following example creates a loop that can only be broken as a result of a JVM Error or Thread interrupt:
public void run() {
while(!Thread.currentThread.isInterrupted()) {
try {
//you application logic
} catch (RuntimeException e) {
//log uncaught exception
}
}
}
In order to shutdown the application, you would attach a listener to the TrayIcon which contained a reference to the SocketThread and could stop it by simply interrupting it.
socketThread.interrupt();
I'll leave figuring how to add an ActionListener to a TrayIcon up to you.