Copyright (c) SEMM NL All rights reserved.
Author : Paul Hamaker. Part of JavaLessons.com
Heart of the matter.
Two Thread derived classes are used .
Both of whom want to change this data.
Their running will be controlled by these ....
and whose turn it is, by this boolean.
When the mouse is clicked, we check if task1 doesn't exist already :
and we initialize the data and the booleans :
The first task thread is created, passing a reference to the applet instance.
Then it is started ,....
so it enters its run method.
MEANWHILE, the main thread has returned and continues by creating and starting the second thread,
so this will enter ITS OWN RUN METHOD.
As you see, two threads have branched off from the main thread. Now we have 3 threads running simultaneously.
The main thread continues, while the other two are executing their run methods.
Let's take a look at OurThreadOne's constructor .
Here, the reference to the applet, app, is copied to the creator reference variable.
This is used in the run method.
super("Uno") means, that the name "Uno" is passed to Thread's constructor, which is OurThreadOne's superclass.
This name is not used here, but could be convenient for debugging.
Having entered its run method, this thread has probably already gotten around to :
Now it enters the applet's getData method, assuming the other thread hasn't beaten it to it :
Because this method is SYNCHRONIZED, ONLY ONE THREAD can enter it AT A TIME.
If a thread is running normally through such a method, this method will be LOCKED FOR OTHER THREADS.
ALL OTHER SYNCHRONIZED METHODS WILL BE LOCKED for this instance , TOO !
Still assuming the first task thread got here first, the other thread is going through its own run method and tries to call this method, too, but it won't succeed.
It has to wait for the method to become available, to be unlocked.
In getData we check if it is the first thread that's currently executing the method ....
and whether it is its turn :
(=AND NOT task1sTurn)
Since it is, the rest of the while is skipped and it continues here.
It returns to its run method with the data, causing the getData method to become unlocked, so the second thread can enter it.
This second thread gets stuck here, because it is not its turn yet.
It has to wait.
The WAIT command causes the SYNCHRONIZED methods to become UNLOCKED, so the first thread can now enter the setdata method.
Thus preventing a deadlock situation.
In setData the same checks are present, to see which thread has entered the method and whether it is its turn.
The data is changed to the received parameter, data plus 100000, that is.
and the TextField is set to it :
The boolean task1sTurn is changed to indicate that it's now the second thread's turn :
And, VERY IMPORTANT, the second thread, still waiting in the getData method, is now told it can continue :
wait, notify and notifyAll can be used only in synchronized methods/blocks.
After changing the TextField's contents, its colour is set accordingly.
When the threads have to be stopped, we give them the opportunity to do so in an orderly fashion, so they can finish what they are doing at that moment :
This takes place in the applet's stop method :
While one or both are still running,....
we'll pause for 5 milliseconds,....
And when they both have finished, exited their run methods, we set their references to null.
DON'T kill a thread by using task.stop( );
Let it end its life gently, as shown.
Pausing both threads is easy, since both look at the pause boolean that's set in the applet :
In the example a green TextField can only contain values like :
50800508, 83700837, and the likes, because the second thread adds one to the data.
yellow : 102501024, 110701106, etc..
stop, suspend and resume in the Thread class are DEPRECATED methods, DON'T USE THEM, they will eventually disappear.