Your java programs always have a number of threads going concurrently. For example, there is a thread for your main program, and another thread for the garbage collector. Other threads may be taking care of operating systems needs, graphics, etc.
New threads of execution can be created by defining a subclass of the class Thread or by declaring a class to implement the Runnable specification. We'll focus here on defining a subclass of Thread.
Other things can happen to a thread while it is running:
If it runs to completion or a "stop" message is sent to it then it moves to a "dead" state.
If it issues an I/O request it moves to a blocked state until the I/O request is completed, and then moves to the "ready" state again.
If a "sleep(n)" message is sent to it, then it waits for at least n milliseconds, and then returns to the ready state. Used when want fixed delay time.
If a "suspend" message is sent to it, then it stays in the "suspended" state until a resume message is sent to it. Good if you know which thread to restart.
If a wait message is sent to it, then it goes into the "waiting" state where it waits in a queue. The first item in the wait queue goes into the "ready" state on a call to notify by another thread associated with the object. A call of notifyAll puts all of the threads on the wait queue in the "ready" state. Used when you don't know who is waiting to proceed. Wakes up whatever thread has been waiting longest.
Can ask thread if it is still alive with isAlive() method.
Note sometimes it is hard to suspend a thread if it is busy. As a result, often have method which sets a flag which can be checked each time through loop to see if want to suspend. See Concurrent Balls example.
In lab Wednesday, will create a timer which can be interrupted and reset.
Can set up what is often called a monitor: Data structure which only allows access by one thread at a time.
Can declare methods in a class to be synchronized. Restricts so only one of synchronized methods can be active at a time. (Ordinarily, several methods may be executing methods of the object at the same time!)
When a synchronized method is running, a "lock" is established on the synchronized methods, so that none can be executed until the lock is released by the executing thread.
Use pair of methods wait and notify when must wait on a condition. Wait releases lock and places thread on a queue waiting to be notified that condition might have changed.
Wait and notify can only be invoked from within synchronized methods (or methods called from within synchronized methods).
Use notifyAll if not sure which object is first in queue.
See code for circular buffer in Buffer folder.