So this is really complicated, it took me a while to realize what's actually happening. Hopefully you understand it better than me though.
I have a Swing class that displays the GUI. In the GUI i have a button, and in the Swing class i have a method that is called whenever i click the button.
When that method is called, i call another method in an object called "Manager". The method in manager then calls another method in a class called "Core". That method in Core sets a local variable, and then calls another method in Core, that self-invokes itself.
The problem is that since it's self-invocing, it never stops running, right? And since it never stops running, nothing is ever returned to the first method in Core. And since nothing is returned to that method, nothing is returned to Manager either. And since that method is never called, the GUI class never gets a response, which leaves the GUI frozen.
Horribly sorry for the messy description. I can't post the code unfortunately. I hope anyone gets my point though, someone must have had the same issue before.
Thanks!
EDIT:
I forgot to mention that the Core class is a thread.
Your long-running process is preventing the main Swing thread, the EDT or event dispatch thread, from continuing, and this will make your GUI completely unresponsive. The solution is to do any long-running process in a background thread such as created by a SwingWorker object. Please check out the link called Concurrency in Swing to learn more about use of SwingWorker objects.
Self-invocation is called recursion. It's a powerful technique, but could lead to infinite loops (hanging) if you're not careful. You need to make sure every recursion (i.e. every time the method invokes itself) something changes towards a terminating state. For example, you could have a number that is guaranteed to decrease every recursion and have as exit condition that your number is negative. Another example is that you're recursively "eating up" some data structure, let's say a string, until there's nothing left. Usually this "something that changes towards a terminating state" is passed to the method as an argument. Your recursive method should start with a check: is my argument in a terminating state? If yes, terminate, if no, do magic.
Secondly, with Swing you should be careful not to violate it's architecture. It's not really MVC, but rather a 2-layered framework. If you're interested in how to use Swing, I recommend reading up on design patterns like MVC.
You got a number of problems.
1) Your recursive function needs an exit condition. So something like
public int imRecursive(int arg) {
if (arg > 100) return;
imRecursive(arg++);
}
in that example, imRecursive doesn't get called over and over, it stops once arg reaches 100.
2) With a swing app, only GUI related code should run in the main event-dispatching thread. If your recursive method is long running, you should use a SwingWorker to do it in another thread so your GUI doesn't lock up.
Post some code. You say Core is a Thread, I assume that means class Core extends Thread but we need to see where you are spawning a new thread (calling a method in a class that extends Thread does not make it run in a separate thread).
Your recursive (self-invoking) method, if it never breaks the recursion, will before too long cause StackOverflowError. If you are not getting that then either you are not using a recursive function or breaking the recursion somewhere. The right way to code a method that never terminates is not recursion, it is iteration.
The GUI freezing is almost certainly because some time-consuming processing is occurring in the GUI thread, one more reason to believe that the method in Core is not running in a separate thread.
I don't understand WHY you have to self-invoke your method...
are you trying to do some recursion?
if the method never ends, you got a infinite loop, its not good.
Depending for what you are trying, you may use Java Threads, or, rethink your code.. i bet you're doing something wrong.
You need to analyse your self-invoking method call - This is a recursive call - but every recursive method must have some condition that stops the recursion - check under what conditions in your case you should get such a condition
Related
I've got a question about what would be the correct practice to use the invokeLater method of SwingUtilities.
So to begin, I'd like to confirm that I am understanding it correctly.
From what I understand, changes to the GUI must be done on the EDT, because Swing components aren't thread safe. The invokeLater method takes a Runnable as an argument, and anything contained in that runnable will be run on the EDT. Therefore any calls made to Swing components are put in a kind of queue, which are executed one at a time on the EDT.
With that out of the way, my question then is: what is good practice for using this? From what I can see there are at least two ways to do it:
1) In the main method, place all code, such as GUI creation, Controller creation, and even the Model creation (assuming a MVC type pattern), in a Runnable that is invoked by the invokeLater method. Of course, this is assuming that any long running tasks in the Model would be executed with a SwingWorker.
2) Place GUI creation in a invokeLater, but Controller creation and Model creation in the main method. Then whenever you need to access a Swing component from a Controller, you pop said code in an invokeLater method to place it on the EDT queue.
What one of these two would be considered best practice, or bad practice? And if neither of these two are good, what would be the better way to go about this?
Any info would be hugely appreciated.
Thanks.
That's indeed an interesting question and the accepted answer isn't fully responding it.
Both approaches you suggest are acceptable and will work fine, but I believe the first one is better than the second approach (do it all on the EDT, and if there is some long-running tasks do them on a SwingWorker, or a new thread if they're not related to Swing).
Why? As #ThomasKrägler pointed out here:
While you could split these tasks (model, controller and view creation) between main thread and EDT (and possibly gain a few milliseconds until the UI is first shown) it would also complicate the design of the application (multithreading is no easy topic) and litter the code base with invokeLater() calls.
Take into account that the EDT won't need to process anything until the model and controller are initialised (and thus starting the view too). So you can use the EDT to initialise them, as it won't have any negative impact on your UI (there is no UI yet).
Doing it this way, you'll save a lot of invokeLater calls and possible errors forgetting to call invokeLater. Your code will look much cleaner too.
SwingWorker isn't special, it's just some wrappers around common scenarios. It will call invokeLater on your behalf so really both cases you present are just instances of the same thing.
Just make sure you follow these two rules:
1. Don't stall the EDT
2. Perform Swing-related code on the EDT
We are unfortunately stuck for the medium term with having to call a method that can sometimes never return, and forever freeze the thread that called it. Fortunately that actual call interacts with little else in the system, and returns no value. So we're thinking that until we can fix the offending code, we need to run the invocation in a separate thread that we can monitor and interrupt if it exceeds a timeout.
Clearly smarter people than I have already solved this problem and left their gifts in the concurrent package, and since this will be my first use of anything in the concurrent package, I'd just like to confirm that I'm picking the best approach.
So I'm thinking I'd get an ExecutorService by calling Excutors.newSingleThreadExecutor, submit a Runnable to it, and then call the overload of Future.get() that accepts a timeout as a parameter.
The actual task to perform is just to call a single void method on an object that I can pass into the constructor of the Runnable.
If this is the right approach, or close, I'd also really appreciate a short code sample if you're feeling generous with your time. :)
Thanks
Clearly smarter people than I have already solved this problem
Actually its not really solved IMHO.
To interrupt a task it has to be well behaved and check the interrupt or it won't actually stop. However, if its well behaved its unlikely to need to be killed in the first place.
You can use the deprecated Thread.stop() if you are sure there is no possible side effects. This requires using a plain Thread. Its not ideal even if you "know" this shouldn't cause a problem and again using a flag to stop the task is preferred.
In my Java application with a Swing GUI, I would like to achieve the following.
There is a non-GUI thread running, performing some work. At one point, this thread needs input from the user before it can continue. Then, I would like to make some changes to the GUI, await a specific GUI action (like the user pressing the OK button), get the entered data from the GUI to the non-GUI thread, and let it continue with the computation.
Looking around, I have found a lot of information about how to initiate the execution of a (long running) task from the Swing GUI thread on another thread, but nothing on my problem.
SwingUtilites.invokeAndWait sounds like it does the job, but first, it takes a Runnable argument instead of a Callable, so there is no straightforward way to return a result, and second, it does not solve the problem of waiting for a certain GUI event.
I realize I could make up my own solution using e.g. a CountDownLatch, but to me, the problem seems frequent enough for there to be a standard solution.
So, my questions are: Is this really a frequent problem, and if yes, is there a solution in the standard library / libraries? If there is no standard solution, how would you solve it? If this problem doesn't occur often, why not?
Kicking off the GUI changes is easy, so I assume you're only asking about getting data back to the worker thread.
First, create a Blocking Queue. Have the worker thread call take() on the queue, and it will block. In GUI space, once the user enters valid input, put it on the queue with offer() and the worker thread will receive the data and can continue.
I think, you can use ExecutorService where you can also track progress of your task through Future interface.
java.awt.EventQueue.invokeLater works nicely for running code on the AWT EDT. Propbably best to copy mutable data or better use immutable data. Locks are possible, but a bit dicey.
If you other thread is an event dispatch loop, you could implement something like invokeLater for your thread (but don't make it static!). Probably use it behind some interface that makes sense to the behaviour of the thread - so it's real operations rather than run which is specified as doing anything it pleases. If your thread is going to block, then a BlockQueue is fine, but don't block from the AWT EDT.
java.awt.EventQueue.invokeAndWait is like using a lock. Probably you are going to use another lock. Or perhaps a lock like invokeAndWait on you own thread. If you don't, AWT uses a lock anyway. So, uncontrolled nested locks, that probably means deadlock. Don't use invokeAndWait!
final bool result = doSomething();
SwingUtilities.invokeLater( new Runnable(){
//Runnable method implementation.
//use result in your method like local var.
});
Make sure that your shared data is synchronized use lock objects.
If you need to pass arguments to Runnable just make your local variables final,
and use them in run method.
I am not understanding this concept in any manner.
public class SomeName {
public static void main(String args[]) {
}
}
This is my class SomeName. Now what is thread here.
Do we call the class as a thread.
Do we call this class as thread when some other object is trying to access its method or members?
Do we call this class as thread when some other object is trying to access this object?
What does it mean when we call something in java as thread-safe ?
Being thread-safe means avoiding several problems. The most common and probably the worst is called threadlock. The old analogy is the story of the dining philosophers. They are very polite and will never reach out their chopsticks to take food when someone else is doing the same. If they all reach out at the same time, then they all stop at the same time, and wait...and nothing ever happens, because they're all too polite to go first.
As someone else pointed out, if your app never creates additional threads, but merely runs from a main method, then there is only one thread, or one "dining philosopher," so threadlock can't occur. When you have multiple threads, the simplest way to avoid threadlock is to use a "monitor", which is just an object that's set aside. In effect, your methods have to obtain a "lock" on this monitor before accessing threads, so there are no collisions. However, you can still have threadlock, because there might be two objects trying to access two different threads, each with its own monitor. Object A has to wait for Object B to release its lock on monitor object 1; Object B has to wait for Object A to release its lock on monitor object 2. So now you're back to threadlock.
In short, thread safety is not terribly difficult to understand, but it does take time, practice and experience. The first time you write a multi-threaded app, you will run into threadlock. Then you will learn, and it soon becomes pretty intuitive. The biggest caveat is that you need to keep the multi-threaded parts of an app as simple as possible. If you have lots of threads, with lots of monitors and locks, it becomes exponentially more difficult to ensure that your dining philosophers never freeze.
The Java tutorial goes over threading extremely well; it was the only resource I ever needed.
You might want to think of thread as CPU executing the code that you wrote.
What is thread?
A thread is a single sequential flow of control within a program.
From Java concurrency in practice:
Thread-safe classes encapsulate any needed synchronization so that
clients need not provide their own.
At any time you have "execution points" where the JVM is running your code stepping through methods and doing what your program tells it to do.
For simple programs you only have one. For more complex programs you can have several, usually invoked with a new Thread().run or an Executor.
"Thread-safe" refers to that your code is written in such a way that one execution point cannot change what another execution point sees. This is usually very desirable as these changes can be very hard to debug, but as you only have one, there is not another so this does not apply.
Threads is an advanced subject which you will come back to later, but for now just think that if you do not do anything special with Threads or Swing this will not apply to you. It will later, but not now.
Well, in your specific example, when your program runs, it has just 1 thread.
The main thread.
A class is thread safe when an object of that class can be accessed in parallel from multiple threads (and hence from multiple CPUs) without any of the guarantees that it would provide in a single threaded way to be broken.
You should read first about what exactly threads are, for instance on Wikipedia, which might make it then easier to understand the relation between classes and threads and the notion of threadsafety.
Every piece of code in Java is executed on some thread. By default, there is a "main" thread that calls your main method. All code in your program executes on the main thread unless you create another thread and start it. Threads start when you explicitly call the Thread.start() method; they can also start implicitly when you call an API that indirectly calls Thread.start(). (API calls that start a thread are generally documented to do so.) When Thread.start() is called, it creates a new thread of execution and calls the Thread object's run() method. The thread exits when its run() method returns.
There are other ways to affect threads, but that's the basics. You can read more details in the Java concurrency tutorial.
I tried to make a event dispatcher in Java that will dispatch events as threads. So all the EventListener classes are essentially implemented the Runnable class. Like how firing of events work traditionally, a method in the event dispatcher class loops through a list of EventListeners and then invoke their handler method, except that this time, I invoke these handler as threads by putting the listeners into new Thread(handlerObject).start(). The actual handling is done in the run() method in the EventListener.
So it looks something like:
for(EventListener listener : listenerList) {
if(listener instanceof Runnable)
new Thread(listener).start();
}
So all instructions to handle the event in the listener are put inside the run() method, which will be executed when the thread.start().
But the problem is the threads often go into a situation where one of the threads got stuck somewhere and didn't manage to continue. Sometimes, several threads may also get stuck while some managed to run through all instructions in the run() method in the listener. I looked up and this sounds like what it is called a deadlock.
I tried to put the "synchronized" modifier to all my methods but it still has this problem. I thought the synchronized keyword would simply just queue any threads trying to run a similar method until a current thread running the method has finished. But this doesn't solve the problem still. Why doesn't synchronized solve the problem especially when I already have it on all my methods and it should queue any concurrent access that may potentially cause a deadlock? I didn't use any wait() or notify() methods. Just a simple event dispatcher that attempts to run its event listener as a thread.
I am pretty new to threads but have found it very difficult to even debug it because I don't know where has gone wrong.
Thanks for any help.
Deadlock is something along the lines of this:
A needs iron to make tools, asks B for
iron
B needs tools to make iron,
asks A for tools
Neither will complete. Just because you've put the syncronized key word around them does not guarantee that you're going to run into a logical impossibility. You have to judge when one thing will be able to move forward and when it won't.
Never just add synchronized to all methods, this solves nothing - you will effectively make your program single-threaded.
When you think you have a deadlock, you can take a thread dump and analyze the output to understand what each thread is executing, which locks (if any) they are holding, what locks they are waiting for, etc.
Unfortunately without specific code or understanding the actual synchronization going on in your application, the only advice that can be given is general like this.
I don't know what you mean by 'deadlock despite synchronized keyword'. The `synchronized' keyword doesn't prevent deadlocks. It can cause them, if you have two threads that acquire locks in different orders. Solution: don't.
Your real problem is that you don't understand concurrency well enough to understand why your program is not working, let alone how to solve this. (FWIW - adding synchronized to all of your methods is only making the problem worse.)
I think that your best plan is take time out to do some reading on concurrency in Java. Here are a couple of good references:
The Java Concurrency Tutorial Stream.
Java Concurrency in Practice by Brian Goetz et al.
#wheaties has a micro-explanation of what a deadlock is, and #matt_b offers useful advice on how to diagnose a deadlock. However, these won't help a lot unless you know the right way to design and write your multi-threaded code.