Java - State pattern: Using threads within the states - java

I want to coordinate serial requests coming from a Java Swing GUI using the state pattern. When a state method was called, the serial communication shall start and in parrallel the GUI should not be frozen during this time.
I have one GUI Thread. In this thread I'm invkoing methods of a state machine which also lives in the GUI Thread.
In some cases after a state machine method has been invoked, data from a serial port shall be fetched (longer task). This fetching is been done in an otherThread. On some state changes the otherThread can be interrupted and otherThread should stop immediately (I'm using otherThread.interrupt()). To know when otherThread actually has returned, I use otherThread.join() to wait for otherThread in the GUI Thread.
Without using join() I always run into exceptions after a state change where I communicate via serial port in another otherThread.
The inconvinience of this approach is ofc. that the GUI thread is blocked/frozen as long as otherThread needs to finish its task.
I was thinking about calling the state machine method in a third thread. But I don't like this idea bcs.:
I don't have a lot experience with multi threading in Java (I assume labeling the methods of the state machine as synchronized could work to ensure thread safetiness).
Overhead due to thread and runnable creation for each invocation of a state machine method.
So my question is: What is a good way to make the GUI not frozen while waiting for otherThread?

All the stuff about "states", "state machines", and "state pattern" is red herring. (Meaning: it is completely irrelevant.) The question is simply how to avoid block-waiting for Thread.join() from the gui thread.
Your "otherThread" should be aware of the fact that it was interrupted and exit gracefully. (Look for more information on thread interruption in Java to see how to accomplish this correctly.)
Right before exiting, the "otherThread" should post a message back to your "gui thread" to let it know that it is exiting.
Posting a message back to the "gui thread" in Swing is done with SwingUtilities.invokeLater(), and the "message" is not exactly a message, it is a function that you pass to invokeLater() and it gets executed within the "gui thread".
Then, the "gui thread" can then either ignore the thread, or join with it, knowing that this Thread.join() will complete very quickly because thread termination is either imminent, or has already happened.

Related

What exactly is a blocking method in Java?

The definition of a blocking method is very clear. There is still something that puzzles me. In a Java program, if I create a thread and try to take() from an empty BlockingQueue, that thread becomes in WAITING state according to the debugger. This is as expected.
On the other hand, if I create a thread and try to call accept() method of ServerSocket class(This is also a blocking code according to the JavaDoc), I see that this thread always in RUNNING state.
I am expecting a blocking method to be parked with monitors in Java. If a method is blocking like ServerSocket::accept, how come this method does not progress accept line and still have the status of RUNNING?
There's the concept of 'a blocking call' / 'a blocking method', as one might use in conversation, or as a tutorial might use, or even as a javadoc might use it.
Then there is the specific and extremely precisely defined java.lang.Thread state of BLOCKING.
The two concepts do not align, as you've already figured out with your test. The BLOCKING state effectively means 'blocking by way of this list of mechanisms that can block' (mostly, waiting to acquire a monitor, i.e. what happens when you enter a synchronized(x) block or try to pick up again from an x.wait() call: In both cases the thread needs to become 'the thread' that owns the lock on the object x is pointing at, and if it can't do that because another thread holds it, then the thread's state becomes BLOCKING.
This is spelled out in the javadoc. Here's the quote:
A thread that is blocked waiting for a monitor lock is in this state.
('monitor lock' is JVM-ese for the mechanism that synchronized and obj.wait/notify/notifyAll work with, and nothing else).
Keep reading the full javadoc of that page, as the detailed descriptions of these states usually spell out precisely which methods can cause these states.
This lets you figure out that if you write this code:
synchronized (foo) {
foo.wait();
}
then that thread goes through these states, in the worst case scenario)
RUNNING -> BLOCKED (another thread is in a synchronized(foo) block already).
BLOCKED -> RUNNING (that other thread is done)
RUNNING -> WAITING (obj.wait() is called, now waiting for a notify)
WAITING -> BLOCKED (we've been notified, but the thread still cannot continue until that monitor is picked up again, that's how wait and notify work).
BLOCKED -> RUNNING (got the lock on foo)
So why is my I/O thing on RUNNING then?
Unfortunately, I/O-related blocking is highly undefined behaviour.
However, I can explain a common scenario (i.e. what most combinations of OS, hardware, and JVM provider end up doing).
The reason for the undefined behaviour is the same reason for the RUNNING state: Java is supposed to run on a lot of hardware/operation system combos, and most of the I/O is, in the end, just stuff that java 'farms out' to the OS, and the OS does whatever the OS is going to do. Java is not itself managing the state of these threads, it just calls on the OS to do a thing, and then the OS ends up blocking, waiting, etc. Java doesn't need to manage it; not all OSes even allow java to attempt to update this state, and in any case there'd be no point whatsoever to it for the java process, it would just slow things down, and add to the pile of 'code that needs to be custom written for every OS that java should run on', and that's a pile you'd prefer remain quite small. The only benefit would be for you to write code that can programatically inspect thread states... and that's more a job for agents, not for java code running inside the same VM.
But, as I said, undefined, mostly. Don't go relying on the fact that x.get() on a socket's InputStream will keep the thread in RUNNING state.
Similar story when you try to interrupt() a thread that is currently waiting in I/O mode. That means the I/O call that is currently waiting for data might exit immediately with some IOException (not InterruptedException, though, that is guaranteed; InterruptedException is checked, InputStream.read() isn't declared to throw it, therefore, it won't) - or, it might do nothing at all. Depends on OS, java version, hardware, vendor, etc.
So the thread states don’t match up with OS thread states. They are defined in https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.State.html:
public static enum Thread.State
extends Enum<Thread.State>
A thread state. A thread can be in one of the following states:
NEW
A thread that has not yet started is in this state.
RUNNABLE
A thread executing in the Java virtual machine is in this state.
BLOCKED
A thread that is blocked waiting for a monitor lock is in this state.
WAITING
A thread that is waiting indefinitely for another thread to perform a particular action is in this state.
TIMED_WAITING
A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.
TERMINATED
A thread that has exited is in this state.
A thread can be in only one state at a given point in time. These states are virtual machine states which do not reflect any operating system thread states.
When we say something is blocked or waiting, we have broad ideas about what that means. But blocked here doesn’t mean blocked on I/O, it doesn’t mean blocked trying to acquire a ReentrantLock, it specifically means blocked trying to acquire a monitor lock. So that is why your socket accept call shows the thread as running, the definitions are very narrow. Read the rest of the linked Java doc, it is extremely specific about what qualifies as a given state.

Does JFrame setVisibility(false) stop all threads I created?

When executing the command this.setVisible(false), does it stop all threads that are running specifically on that frame?
If not, is there an easy way to stop all of them automatically?
I think we have a conceptual problem here. There are no "threads running on a JFrame." There is one thread, the Event Dispatch Thread, that runs ALL Swing objects, frames, etc.
The EDT (Event Dispatch Thread) does not stop because you made one window invisible. However, if ALL Swing objects become unreachable (eligible for garbage collection) then the Swing EDT does shut down. (The app-note linked below says you can also call Window.dispose() on a frame to make it undisplayable; it then no longer counts for keeping the EDT running.)
The more precise conditions for shutting down the EDT are in this app-note:
Starting with 1.4, the behavior has changed as a result of the fix for
4030718. With the current implementation, AWT terminates all its helper
threads allowing the application to exit cleanly when the following
three conditions are true:
There are no displayable AWT or Swing components.
There are no native events in the native event queue.
There are no AWT events in java EventQueues.
Prior to Java 1.4, the EDT never shuts down. Hopefully you don't need to go that far back.
If you want to shutdown a group of threads, you have to do it manually (other than using some course method like System.exit()). I would look at Executors which enable you to manage threads fairly easily.
No, setting the JFrame visibility to false won't stop all threads you created with new Thread().
If not, is there an easy way to stop all of them automatically?
To stop all of them automatically there is no way (unless terminate all the program)
You need to have them stored in a list or a vector, for example, and then use the method Thread.interrupt()
Something like this:
for(Thread thread : threads) //where threads is a List
{
thread.interrupt();
}
No it does not!
The Thread does still run in background, but you cant interact with the Frame.
To Stop all threads you could do:
System.exit(1) which would terminate all Threads or for every Thread
Thread.sleep(10000000000); which would stop the Thread for a certain amount of time (in milliseconds).

Thread output listener

I need to make a thread that start at swing button push and wait for input from rs232, process it and return String to my variable. The question is how to do that?
it should be something like that:
String myOutputString = waitForInputThread();
Or if its possible in swing panel make something like listener that do something if this waitForInputThread send interrupt (for example, if get rs232 input do update a list of items in JTable).
Could you give me some clues, tutorials, examples etc ?
To avoid blocking the Event Dispatch Thread (which is the thread that updates the GUI), start a new thread to interact with the RS232. The SwingWorker class is one option, but you can just as easily use a normal thread.1 Blocking the EDT causes your GUI to freeze, so it must never be used for lengthy tasks.
Once your result is computed, update the GUI using SwingUtilities.invokeLater(). This ensures the GUI change occurs on the EDT.
1 I tend to find normal threads executed via an ExecutorService are better for unit testing (as you can write an ExecutorService that immediately executes the Runnable, avoiding any nasty thread issues with JUnit).

Java - Run a runnable on an existing thread?

I am trying to switch back to an existing thread from a spawned child interface callback. Does anyone know how? The callback implementation always runs from the child thread where where it was called, not the implementing class...
What do you mean switch back?
Cause a context switch that will return you to "original" thread that spawned the child thread?
If so, this is not possible. It contradicts Multi-threading concepts.
If you want to have some work done on the "original" thread, while the "child" thread is running,
You can consider having a queue between the child and the original thread (i.e - Producer/Consumer).
The child thread will put a "job" on the queue, and the "original" thread will consume it.
However,the "original" thread will have to block on the the "child" thread.
Another way to implement this is using wait and notify, (child thread will notify) - but once again, original thread will have to wait.
Last approach will be to simply wait on the child thread execution to end, if you want to return to the original thread at the end of execution of child thread.
The question is - is waiting at the original thread is acceptable at your scenario?
You simply have the calling thread wait() on an object, and have the child thread notify() the same object.
When wait() is called, the calling thread will halt.
When notify() is called, the waiting thread will wake up and continue on.
These calls must be made within a synchronized block/method.
Swing uses the concept of an Event Dispatch Loop (EDL), and all Swing component interaction must run on the the EDL's thread. This sounds analogous to what you want to do, and to what zaske proposed in his response.
You might find the following helpful in formulating your solution:
SwingUtilities, in particulare it's invokeLater(Runnable) method.
SwingWorker if you want to get fancy and start even more threads.
Since this is also tagged java-ee I'll mention that you are not allowed to start threads in any Java EE app server. It introduces several issues:
Easy to bleed the server of thread resources
Can prevent undeployment of the application
Can prevent server shutdown if threads are not marked as daemons
Loss of functionality such as JNDI, Transactions, Security
It's generally a no-no. You might instead look into the #Asynchronous annotation which allows you to easily do fork/join kinds of logic safely with the cooperation of the container.
This answer has a very complete explanation of how #Asynchronous methods work including example code https://stackoverflow.com/a/6158773/190816

What is the event dispatching thread?

I know what "thread" means and if I understand the event dispatching thread (EDT) as
"just a thread", it explains a lot but, apparently, it does not explain everything.
I do not understand what is special about this thread. For example I do not understand why we should start a GUI in a the EDT? Why the "main" thread is bed for GUI? Well, if we just do not want to occupy the main thread why we cannot start GUI just in "another thread" why it should be some "special" thread called EDT?
Then I do not understand why we cannot start the EDT like any other thread? Why we should use some special tool (called invokeLater). And why GUI, unlike any other thread, does not start immediately. We should wait until it is ready to accept our job. Is it because EDT can, potentially execute several task simultaneously?
If you decide to answer this question, could you pleas use a really simple terminology because otherwise, I am afraid, I will not be able to understand the answer.
ADDED:
I always thought that we have one "task" per thread. So, in every thread we execute a predefined sequence of commands. But it seems to me that in the event dispatching thread we can have sever task. Well, they are not executed simultaneously (thread switches between different task but there are still several task in one thread). Is it right? For example there is one thread in the EDT which display the main window, and then additionally to that we sent to the EDT another task which should update one of the window components and EDT will execute this new task whenever it is ready. Is EDT differ from other threads in this way?
The event dispatching thread is the thread that handles all GUI events and manages your Swing GUI. It is started somewhere in the Swing code if you have any GUI in your program. The reason it is done behind the scenes is because of simplicity - you do not have to bother with starting and managing an extra thread by yourself.
Regarding the fact that you have to update your GUI with invokeLater() it is because of concurrency issues. The GUI can be modified only from one thread because Swing is not thread safe(it is worth to note that most of toolkits are not thread safe, there is a nice article that gives some ideas why). This is why you have to submit all GUI updates to run on EDT.
You can read more on concurrency in Swing and event dispatching thread in Sun tutorial on concurrency in Swing. Also, if you would like to see how this could be done in a different way you might like to check out SWT toolkit. In SWT you have to manage EDT by yourself.
I always thought that we have one
"task" per thread. So, in every thread
we execute a predefined sequence of
commands. But it seems to me that in
the event dispatching thread we can
have sever task. Well, they are not
executed simultaneously (thread
switches between different task but
there are still several task in one
thread). Is it right? For example
there is one thread in the EDT which
display the main window, and then
additionally to that we sent to the
EDT another task which should update
one of the window components and EDT
will execute this new task whenever it
is ready. Is EDT differ from other
threads in this way?
No, the EDT is not fundamentally different from other threads. And "task" is not a good word to use, because it could be confused with OS-level processes (which are also often called task). Better use Runnable, the interface used to give code to the EDT to execute via invokeLater().
The EDT is basically connected to a queue of things it has to do. When the user clicks a button on the GUI, a Runnable that notifies all listeners attached to the button goes into the queue. When a window is resized, a Runnable doing revalidate&repaint goes into the queue. And when you use invokeLater(), your Runnable goes into the queue.
The EDT simply runs an endless loop that says "take a Runnable from the queue (and if it's empty sleep until you're notified that it's not) and execute it.
Thus, it executes all those little Runnable pieces of code one after another, so that each of them basically has the GUI all to itself while it runs, and doesn't have to worry about synchronizing anything. When you manipulate the GUI from another thread, this assumption is broken, and you can end up with the GUI in a corrupted state.
What is the EDT?
It's a hacky workaround around the great many concurrency issues that the Swing API has ;)
Seriously, a lot of Swing components are not "thread safe" (some famous programmers went as far as calling Swing "thread hostile"). By having a unique thread where all updates are made to this thread-hostile components you're dodging a lot of potential concurrency issues. In addition to that, you're also guaranteed that it shall run the Runnable that you pass through it using invokeLater in a sequential order.
Note that it's not just that you're dodging the concurrency issue: you must respect Sun's guidelines regarding what must and what must not be done on the EDT or you'll have serious problems in your application.
Another benefit is that some Swing components tend to throw unwanted exceptions and when this happen they're automagically dealt with and won't crash the EDT (AFAIK if you really manage to kill the EDT it is automagically restarted).
In other words: you don't have to deal with all the broken Swing components and the exceptions they throw yourself: the EDT is taking care of that (just take a look at the countless Swing bugs throwing exceptions in Sun's bug parade, it's fascinating... And yet most apps keep working normally).
Also, by doing only what's mandatory in the EDT allows the GUI of your app to stay "responsive" even tough there may be tasks running in the background.
The important thing to remember is that Swing classes are not thread-safe. This means that you always should call Swing methods from the same thread, or you risk getting weird or undefined behavior.
So the solution: only call Swing methods from a single thread. This is the EDT thread - it's not special in any way other than that it is the thread designated to call swing methods from.
Now you may ask why are Swing methods not thread safe? After several unsuccessful attempts, GUI toolkit designers discovered that it's inherently impossible to design a thread-safe GUI toolkit. Too often events are passed in opposite directions (input events from bottom to top, application events from top to bottom) which always leads to deadlocks. So that's just the way it is.

Categories

Resources