JTabbedPane+MultiThreading: Open tab in a new thread - java

Good day, I want to make in java swing opening tabs in new threads and it would have had the opportunity to run time-consuming tasks to switch between tabs. Tried it, a copy of the tab implement the interface Runnable, but a new thread is not valid (in the debugger it starts hanging about 1 sec, and is killed), as I understand the constructor work out, and all the contents of the swing is placed in its major flows. I read about SwingWorker, but do not quite understand how you can apply it to my problem. If you can, please show an example. Thanks in advance.
P.S. This is network application, and "load" will serve as a work with the server. That is, in other words, to give the user the ability to switch between tabs until the current tab is a connection.

You should try to separate the code that does the actual work from code that specifies the GUI. You should search e.g. for the Model-View-Controller-Pattern (MVC).
This way the GUI code can run inside the event-dispatcher-thread (EDT) of Swing / AWT how it is more or less inteded. The code that does the actual work should be as independent from the GUI as possible. Now you can choose to run it in a dedicated thread or whatever fits best into you overall application architecture.
The last part is wire these two (the GUI and the domain logic) together, so that the GUI triggers the worker code or the worker code triggers GUI updates, or whatever satisfies the workflow requirements.

Related

JFrame gets locked completely while method is running

I have a GUI(JFrame), with two Buttons and 1 Panel to show the result. One Button is to start the algorithm, one for stopping it. By pressing start, a method is called and it starts running. The runtime of this method varies from couple of seconds to 2-3 minutes, depending on the input.
The problem I have hereby is, by pressing the start-button, the GUI gets completely locked. I cannot press any button till the algorithm terminates. It would be great to be able to stop the algorithm and to visualize parts of the solution after a certain amound of time.
I checked every single line of the Frame, there is nothing that disables it.
//If needed I can provide code, but its pretty long and just some hints and reasons for the problem would be great and I try to fix it by myself.
thanks in advance.
Don't put long-running tasks on the EDT, or the Event Dispatching Thread. Use threading or a SwingWorker instead. Hopefully that's enough google keywords to get you started. :)
It sounds like your algorithm is running in the same thread as the UI components. You probably want to read up on Concurrency and Concurrency in Swing to better understand how to create threads, monitor execution, integrating these concepts with a Swing-based user interface, and so forth. At a very high level, you are going to need to somehow spawn a new thread when your algorithm starts and observe it for intermediate state changes to update the UI. You only want user interface related code running in the event dispatch thread.

Can I run two EDTs?

This is mostly a theoretical question. The example below is what made me think of it, but it may not be the best example. Please assume that the reason's below are concrete, and can't for the moment be worked around.
The Program I have been running has an optional Debug frame that is created on the program startup, and it made visible by the user pressing buttons/keyboard shortcut.
My issue is that as I have lengthy processes on the EDT, if it is hanging for some reason or fails I'd like to see straight away, and not wait for that thread to end running, to update the Debug Log Frame.
My solution would be to have two separate EDT for two separate GUIs that are updated by a separate thread.
Is this possible, or am I not able to do so? I haven't found any online resourcethat would show me how to. I know that EDTs should be single threaded, but if I keep the threads disentangled, can I have two? Please?
The answer is simple: No you cannot have 2 EDTs, that is not possible.
But you are not stuck with a frozen GUI, you have some options available.
First and foremost, two important rules:
Never do lengthy calculations in the EDT. Ever.
Never manipulate Swing components from outside the EDT. Ever.
Breaking the first rule will result in your GUI being frozen and no events of any sort being processed during that time. This includes updates to the GUI you want to do during the calculations which will not appear until after the calculations are done.
The latter is often ignored which will go by unnoticed most of the time, but it can - and will - bite you in the ass and then most of the time it is a huge pita to go back and fix it. So do it the correct way from the start. What can happen? Components can suddenly display in a broken state, they may appear white, or the whole application can freeze because there is a deadlock between the EDT and your other threads (been there, done that). Adhere to the Oracle Swing Threading Policy!
So, how to avoid doing lengthy calculations on the EDT after for example the user pressed a button? Options:
use a SwingWorker. Advantage: Has a done() method you can use which is automatically executed in the EDT once the worker is done. Also implements the Future interface and can therefore be used to return a result.
you can just create your own Runnable and do the calculations in there.
use any other way Java provides for parallel execution.
Ok, and how to avoid ever manipulating GUI from outside the EDT?
call SwingUtilities.invokeLater() and execute Swing manipulations in there.
use the SwingWorkers done() method as described above.
If you follow these two rules, your Swing GUI will be in a much better shape and you can focus more on your application development rather than Swing issues.

Use of multiple threads in a Java program and vs need to create Swing objects on EDT

Re: Requirement to create Swing Object on Event-Dispatch Thread.
I am working on an application, the purpose of which is to monitor and display the condition of various remote embedded servers. I'm pretty new to Java, and my understanding of the requirement with respect to the Swing Objects and the EDT is incomplete.
The main GUI is started on the EDT in the usual fashion as follows,
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
The user may then select one or more menu options corresponding to the one or other of the remote machines. The effect of this is to create a new thread each time as follows
new Thread(new VoterStatus(itemNumber)).start();
which invokes VoterStatus's class "run" method which in turn creates a new window with a JFrame. The new thread, an instance of VoterStatus class, then interrogates (TCP etc) the particular remote specified (itemNumber), collecting various bits of information and displaying them in the JFrame.
There may be any number of such threads corresponding to an instance of VoterStatus, all updating their own windows. There is no sharing of data between these various windows/JFrame/tasks.
This seems to work just fine, but is is safe?
Have I violated the rule about creating Swing components on the EDT?
Would use of the SwingWorker class be beneficial?
I would appreciate any comments from Java programmers more experienced in such matters.
Thanks
Steve
From the section in the Swing tutorial titled The Event Dispatch Thread
Some Swing component methods are labelled "thread safe" in the API specification; these can be safely invoked from any thread. All other Swing component methods must be invoked from the event dispatch thread. Programs that ignore this rule may function correctly most of the time, but are subject to unpredictable errors that are difficult to reproduce.
I always invoke my methods on the EDT so I don't waste time chasing gremlins.
Edit:
I just read another posting which states that the comment "thread safe" has been removed from many methods in the JDK7 API. http://forums.oracle.com/forums/thread.jspa?threadID=2167051. This looks like another reason to make sure all methods that affect the GUI are executed on the EDT.
#camickr has the right of it. Incorrectly synchronized programs may appear to work most of the time, but the result is not reliable. Several related approaches are discussed here. SwingWorker is an especially convenient implementation of the Future interface, as process() runs on the event dispatch thread.
You might be safe, but you can be sure by creating your other UI components in the EDT, just like you did for the main application.
However, I would suggest a different approach. Rather than firing off a new Thread which creates the windows and stuff for each new VoterStatus, create the UI components in the EDT in response to ActionEvents from menus or whatever, and do processing of the network stuff only in a different thread. Then get the results and use the EDT to display them. As you've suggested, a SwingWorker is ideal for this - this is exactly the sort of use it was designed for. This represents a cleaner separation for me, separating the UI stuff from the network stuff as much as possible.
I'm not really answering my own question, but I do want to thank those that responded and ask a follow up question or two.
Rogash commented that if I was only creating the GUI on the EDT, I would be ok, but this doesn't seem quite in accordance with a strict interpretation of the rule?
The additional threads are created in the EDT, but they are still separate threads.
Whilst slightly better separation of the GUI and comms may be desirable, I expect this will add considerable complexity to the main GUI code, since it will have to determine which window originated various events and then update the correct window, not to mention the communication between the various threads and the main GUI thread. Perhaps I am overstating this difficulty (I haven't designed or thought about how to code it yet) but it would seem more complicated. Each of the threads/JFrame already has a couple of JToggleButton arrays (30 elements) causing potential events and 10 or so JTextField arrays with the same number of elements requiring updating.
Of course, if my method is unsafe, I'll have to change it, and that's that!
Actually, I wonder if I might be better off leaving things the way they are, and using a mutex or semaphore to make sure only one thread is accessing Swing methods at a time. There is really no long user actions or any other activity takes a long time, just lots of TCP or UDP packets being received that require the screen display to be updated.
Thanks again
Steve
PS I tried to register on this forum, but I think this discussion will stay with my unregistered persona.

Swing "blocking", I think I need to thread, but not sure how much

I have a little java app to effectively "tail" an arbitrary collection of files defined in an ini file. My "LogReader" class extends JFrame, and does the heavy lifting; reading the collection of file paths into a vector, and then iterating over the vector, reading each file and adding the last X lines of each to a text areas on the tabs of a JTabbedPane. The process of building the vector and iterating over the files is kicked off by clicking a JButton, via an ActionListener.
The reading of the files worked fine (and still does), but the process of reading 20-some files, some growing as large as 30MB, takes some time. To help pass that time, I decided to add a progress screen, which says "Now reading file #3 of 26: c:\logs\superduper1.log", and so on. So I created another class, "SplashScreen", also extending JFrame, and added a JLabel that would indicate the progress. The SplashScreen class has an update() method, which just does a setText() on the JLabel.
The ActionListener on the JButton calls RefreshLogs(), which looks something like:
vctFileStrings.clear();
tpMain.removeAll();
frmSplash.update("Loading Configuration"); //Update the label on the Splash Screen instance
BuildVectorOfLogs(strConfFile); //Read the collection of files into the vector
frmSplash.update("Reading Logs");
ReadLogs(); //read the files, updating the Splash Screen as we go
and then ReadLogs() iterates over the vector, reading the files and building the TabbedPane.
What I noticed, though, is that when RefreshLogs() is called from within the ActionListener, the Splash Screen doesn't update. However, if I add RefreshLogs() to the constructor of the first frame, the splash screen works as expected (updates progress on each file). After some experimenting and reading, I think that I need to create a worker thread that reads the files, while updating the splash screen in the event-dispatch queue.
My questions are:
- Is my thought correct? Is there some simple alternative to implementing threading that would allow me to update the splash screen from the method called by the ActionListener?
- If this would be best accomplished using threading, what scope of the activity would I need to thread? Would I need to put all of the file I/O activities into their own thread? Should I put the GUI activities (label updates) in their own thread, so they occur separately from the JButton click event?
I would say: yes, your thoughts on offloading the reading of large files to a separate thread are correct. You should never perform long tasks on the Event Dispatch Thread, since while that thread is busy, the GUI will be unresponsive, and you application will feel slow.
This sounds like good case for SwingWorker. This class allows you to perform slow requests (such as disk or network access) on a separate thread, with progress updates being fed back to the GUI with the EDT. SwingWorker looks after all complexities of switching between threads. All you have to do is implement your business logic in the appropriate places.
Sun has a tutorial on SwingWorker.
Yes, you should put your time intense reading into a separate thread. Now you do everything in the event-dispatching thread (EDT), which would update your GUI but is busy reading your data.
You can use SwingWorker for this. Have a look at Using a Swing Worker Thread which looks like what you need.
One suggestion for you, to figure out how to do this, and in case you are using NetBeans or have access to NetBeans, is to look at the default Java Desktop Application template. It creates a pre-wired desktop app with progress bar built into a status bar, that will automatically get updated when any "Action" code gets executed. It leverages the Action API which is also pre-wired to run in a background thread.
By looking at that auto-generated code you'll be able to properly and easily implement it in your own.

How do I give this CPU-intensive Java application a GUI?

I'm writing a little genetic algorithm in Java, as a school assignment. Up until now I've pretty much stuck to doing console applications. However I think a UI would be really helpful for this program, so I'd like to make one. I'm having trouble figuring out how to reconcile a GUI which is event-driven, and a console application which has a beginning and end.
Ideally I'd like to have a bunch of text boxes for settings, and then a Start button. Once you hit Start, the algorithm would start running and the GUI would update on a set interval with the latest program state. How the heck do I accomplish this without the algorithm freezing the GUI or vice-versa? I don't want either one waiting on the other.
How do I get my main loop to not freeze the GUI while the algorithm is running? I assume they need to be in separate threads, but I've never messed with threads before. That seems too complex for this task, which must be commonplace.
You're on to something with threads. GUI programming mandates threads, in most cases -- luckily, Java's threading API isn't too terrible (Python's is modeled on it, so it's doing something right).
Don't be intimidated by threading, though -- it's intermediate, I'd say, but is something that every programmer should understand.
There's a lot of information out there that would predispose you against threads. GUI applications, however, are one area where they are phenomenally useful. Opponents of threading would lead you to believe that an event-programming model would help you in this case, when really, it will not. The solutions that most who say "threading sucks" propose are often worse than threading itself.
You could try to kludge your solution into a single thread, but it would require your CPU-intensive code to yield to the GUI at a predictable interval. That solution sucks. EDIT: Since others are suggesting that approach, let me elaborate on why it sucks: Unbeknownst to you, something is always being updated in a GUI. When you move a window on top and then back off, the entire region under that window is invalidated and code must execute -- in your process -- to redraw that section. Even if you are updating the GUI very quickly, this provides a negative user experience as simple GUI operations block entirely. Buttons highlight when you mouse over, sometimes. A user right clicks. All of these things require CPU time to implement, and if your solitary thread is chewing away on your GA, they will not happen. GUI code being executed is not only your code.
Here's what appears to be a very useful article on the topic.
Two lessons in the trail on the topic are:
Concurrency
Concurrency in Swing
Sorry - it would seem like background tasks would be an easy and obvious sort of thing. Unfortunately, the Java Swing GUI threading model is a bit complicated. There have been some improvements in this area, but one still has to have some knowledge of threading first.
If you have time, I'd suggest reading the chapter on threading in Filthy Rich Clients - Painless Threading through SwingWorker.
If your impatient, just read the JavaDoc on SwingWorker. If you're really impatient, just copy the meaning of life example from the JavaDoc sample usage.
When I was writing a ray-tracer for one of my computer graphics classes in college, I had a long-running task, and I wanted to update the display periodically as the tracer was drawing. I used two separate threads - one thread sleeps, and updates (say every 500 ms); the other thread does the actual raytracing. The key is to synchronize on a common object - in my case, accessing my image buffer was the point of synchronization (one thread can't make changes to the image buffer without first waiting until the other thread is done reading).
For your GA processing, you might have something like this (pseudocode):
Supposing you have some object, generationHistoryObject, which stores the state that you want to display in your GUI, then:
(in Thread #1:)
Generation newGeneration = doMutationAndTestThisGeneration(lastGeneration);
synchronized (generationHistoryObject) {
generationHistoryObject.updateWithNextGeneration(newGeneration);
}
(in Thread #2:)
while (!programIsDone()) {
synchronized (generationHistoryObject) {
drawGuiForCurrentState(generationHistoryObject);
}
Thread.sleep(500);
}
The idea is that you do the time-consuming work for each generation in isolation, then update the part that the GUI has to access in the synchronized block (making the GUI wait to draw until the update is done).
Your problem with Swing is that it is single threaded (which is a good thing) so you want to get your work out of the Swing thread so your application stays responsive.
The thing you need to do is to convert your core algorithm to a Runnable as it can be handled easily by a SwingWorker and with the newer Executors (see Executors for a lot of preconfigured ones). You can also create investigate how to make a PrintStream to a JTextPanel so you can just use standard println statements to output your current status information.
If you want to add a stop button you need to understand the thread model, so you know how to control it. The Java Tutorial has good material on this as well as Swing programming in general. Strongly recommended.
http://java.sun.com/docs/books/tutorial/uiswing/concurrency/index.html
Since your application has to do with genetic algorithms, you could update the GUI every generation or so. You could accomplish this by implementing a next() method in your algorithm code, and calling it from the GUI. This should be simple enough.
However, if you really don't want the GUI to freeze while waiting for the algorithm, you should go for threads.

Categories

Resources