| Threads are software engines that can process any sequence of instruction. Everything in Java happens because of a thread executing a method. | |||||||
| When a JVM starts up, there is usually a single non-daemon thread (which typically calls the method named main of some designated class). | |||||||
The JVM continues to execute threads until either of the following occurs:
|
|||||||
| Mutithreaded | Java is multithreaded. A program can have multiple processes running. Each thread has its own path of execution. But can potentially access any object in the program. | ||||||
| Multithreaded is built into the operating system to be cross-platform. | |||||||
| MultiTasking | In systems that do not have multithreaded, the task would occur one after the other. With multithreads, the tasks can occur simultaneous as multitasks. Tasks are switch rapidly between different applications. | ||||||
| run() | Threads carry out their behavior by coding the public void run() method. This method is overriding to generate specific processing. | ||||||
| java.lang.Thread implements Runnable | java.lang.Thread is the base class of all threads. There are two ways to create threads:
|
||||||
| java.lang.Thread implements the Runnable interface | |||||||
| The Thread class conceals the details of a particular operating system’s approach to multithreading. | |||||||
| The JVM creates and runs sever Threads to support even the simplest Java program. | |||||||
| Thread Constructors | |||||||
| Thread() | Automatically generates a name for the Thread (null, null, name).
The name is generated as “Thread-“+n. n is an integer. |
||||||
| Thread(Runnable) | Automatically generates a name for the Thread (null, target, name) plus the target object who has a run() method. | ||||||
| Thread(Runnable, String) | Provides a name for the Thread (null, target, name) plus the target object who has a run() method. | ||||||
| Thread(String) | Provides a name for the Thread (null, null, name). | ||||||
| Thread(ThreadGroup, String) | Provides a name and a threadgroup for the Thread (group, null, name). | ||||||
| Thread(ThreadGroup, Runnable, String) | Provides a threadgroup, target and name for the Thread (group, target, name). | ||||||
| Thread(ThreadGroup, Runnable) | Provides a threadgroup and target for the Thread (group, target, null). The name is automatically provided. | ||||||
| Extending Thread | The easiest way to create Threads are to extend the Thread base class. | ||||||
| Class that extend the Thread class execute their behavior in parallel fashion only once. | |||||||
| The behavior to be carried out is tightly related to the class’s object. | |||||||
| Declaring | public class MyThread extends Thread {
public void run() { } } |
||||||
| Instantiating Thread | To get an instant of the thread do the following:
MyThread t = new MyThread(); |
||||||
| start() | Creating a thread with run() method does not mean it is doing anything. To start a thread the start() method must be called. | ||||||
| t.start(); | |||||||
| The instruction specified in the run method will execute in parallel to what ever follows in the start() method. | |||||||
| JVM scheduling mechanism | Once started it gets connected to the JVM scheduling mechanism and executes code in the run() method. | ||||||
| Using a Runnable interface different instances of the thread can be started. | |||||||
| Exam Tip | If a thread is started that has been already started an IllegalThreadStateException occurs. | ||||||
| Runnable Interface | A class can only extend one other class. For it to also use threads, the class must implementing the java.lang.Runnable interface. | ||||||
| target of thread | An instance of this class maybe the target of one or more threads. Passed as an arguments. | ||||||
| The runnable interface defines only one method:
public void run() |
|||||||
| public class MyRunnable implements Runnable {
public void run() { } } |
|||||||
| Exam Tip | The run method cannot throw checked exceptions. | ||||||
| Instantiating | To get an instant of the thread do the following:
MyRunnable t = new MyRunnable(); |
||||||
| MyRunnable is a target for a thread. | |||||||
| Thread t = Thread(MyRunnable); | |||||||
| Exam Tip | An instance of Thread with no Runnable target serves no purpose | ||||||
| Exam Tip | A thread instance can only be started once. | ||||||
| Thread static Methods | Thread.currentThread() | Returns the currently running thread. | |||||
| Thread.dumpStack() | Trace the execution of the currently running thread. | ||||||
| Life of a Thread | Threads have life cycles. There are four states: | ||||||
| New | A thread is Born. | ||||||
| Runnable | It’s in the ready or running state | ||||||
| Ready, Running | |||||||
| Blocked | Yield, seeping, waiting and blocking I/O are the blocked state. | ||||||
| Yield, Sleeping, Waiting, Blocked | |||||||
| Dead | The final state of a thread. | ||||||
| The transition from new to runnable and from runnable to dead is simple and permanent. | |||||||
| The transition between runnable and blocked occupy most of the Java programmer’s attention. | |||||||
| Thread Scheduler | The thread can remain in the runnable state at the mercy (based on
the JVM implementation) of the Thread scheduler. |
||||||
| The thread scheduler can also move a thread from the running to ready state at its own will. | |||||||
| States | Once started a thread goes through various states. | ||||||
| Running | In the running state threads run their methods concurrently with other threads. | ||||||
| They cooperate, share resources and compete with each other to get their task done. | |||||||
| Exam Tip | There is no guarantee that a thread will execute a series of instructions in one go. It may be switched out of the CPU at any time to give another thread the time slice. | ||||||
| Automatic variables | Automatic variables of thread are stored in a special area for protection. This allows thread to be executed safely with unexpected modification. | ||||||
| Member variables. | Member variables can be shared among threads. | ||||||
| Sleeping | A running thread may consume the CPU bandwidth. To give others a chance the current thread may put itself to sleep for specified number of milliseconds. | ||||||
| public static native void sleep(long millis) throws InterruptedException
|
The static method sleep() method delays the execution of a thread for the specified milliseconds. | ||||||
| Thread.sleep(5*60*100f0) | |||||||
| The sleeps for five minutes. | |||||||
| Exam Tip | The elapsed time of the sleep method can not be exact, but at least that amount of time as been expired.
It is not plus or minus the system clock tick |
||||||
| Interrupt | public void interrupt()
|
The current or another thread may wake the sleeping thread by calling the sleeping thread interrupt() method. | |||||
| interrupt() method used in an instance of a thread. | |||||||
| sleepingThread.interrupt() | |||||||
| InterruptedException | When the sleeping thread has been interrupted, it will throw an InterruptedException. Therefore a try-catch block must be used for a sleep method. But will get access to CPU time thereafter. | ||||||
| An internal flag is set in the thread that it has been interrupted. | |||||||
| To reset the thread interrupt flag the current call its interrupt() method.
Thread. interrupt() |
|||||||
| try {
Thread.sleep(sleepingTfime); } catch (InterruptedException){ } |
|||||||
| InterruptedException is a checked exception. It to clears the internal interrupt flag. | |||||||
| Exam Tip | Another class cannot put another to sleep. Sleep is a static method. | ||||||
| Exam Tip | Sleep is not a high-precision timing operation. There is no guarantee that the Thread will immediately be able to execute after the time delay is up. That is up the JVM thread scheduler. | ||||||
| public static boolean interrupted() | Current thread can test if it has been interrupted. | ||||||
| Note that interrupted is a static method, while isInterrupted is called on the current Thread instance. | |||||||
| public boolean isInterrupted() | Another thread can test another threads interrupted status. | ||||||
| Note that isInterrupted is called on the current Thread instance by another thread; by contrast, interrupted is a static method called by the current thread. | |||||||
| Dead State | When a thread exits the run method to which it is attached becomes a dead Thread. | ||||||
| Exam Tip | A dead thread can not be restarted. | ||||||
| Concurrency | Different thread can access the same member data of a thread class. This can cause sharing resources and inconsistent state problem. | ||||||
| Furthermore, the CPU might swap a thread out of its processing time slice while carrying a critical update or reading. | |||||||
| Thread optimize their processing by keeping a local copy of their data member for quick access. However, the local copy may be out of sink with shared memory copy of the data members. In a multithreaded environment the local copy version maybe in and inconsistent state. | |||||||
| volatile | Volatile keyword tells the compiler that a variable to used its shared copy and not the local copy of the thread for reading and writing. | ||||||
| This marks the variable that it can change at any time. | |||||||
| Exam Tip | volatile can only be used on data members | ||||||
| Exam Tip | volatile can not be used in methods | ||||||
| Exam Tip | Don’t synchronized on local objects, it accomplishes nothing. Each thread makes a copy of all automatic variables for its use. It is best to synchronize on member variables. | ||||||
| Synchronize | Each object has an associated lock variable that can be manipulated only by the JVM. | ||||||
| public class Wait() {
public static void main(String arg) }{ synchronized(arg) { arg.wait(); } } } The thread is synchronized on the arg object. |
|||||||
| Monitor | This lock manipulation provides a monitor mechanism that can be used to allow only one Thread at a time to have access to an object. | ||||||
| Because it takes time for the JVM to check every object for a lock, it is ignored. | |||||||
| Synchronize keyword specifies that a method or block of code needs to be guarded by the lock mechanism. | |||||||
| Synchronized keyword signify that a thread must obtain a lock on the object in order to use the block of code or method. | |||||||
| Otherwise the thread is blocked and will get access when the owner of the lock releases it. | |||||||
| Many threads may be blocked. | |||||||
| The JVM ensures that the lock is removed when a Thread exits the code block. Whether or not the exit is normal. | |||||||
| Exam Tip | The order and which object will the lock on the object is not defined or guaranteed. | ||||||
| Exam Tip | A variable cannot be declared synchronized. Code blocks or methods can be synchronized. | ||||||
| Exam Tip | A lock on object is released when the method completes. | ||||||
| In Java every object can be synchronized. Synchronized methods always try to get the lock of the current object. | |||||||
| void notFullySynchronized() {
//Unsynchronized instruction here synchronized(otherObject) { //Safe instruction here } //More unsynchronized instruction here } |
|||||||
| Note synchronization on method is like synchronizing on this object. This is automatically the object reference. | |||||||
| public void analyze() {
synchronized(this) { //All the method is synchronized. } } |
|||||||
| Exam Tip | The volatile keyword is unnecessary when a block of code is synchronized. | ||||||
| Exam Tip | Overriding
If a synchronized method is overriding and the subclass does not have to be declared synchronized. |
||||||
| Exam Tip | The synchronized work affect only the code block in the original class. | ||||||
| Thread Order | Thread.sleep() method works on the thread class, the thread itself, and not the object. The current thread goes to sleep. | ||||||
| To communicate between thread objects we must use the wait(), notify() and notifyAll() methods. It is an object-oriented way of handling threads. | |||||||
| In this scheme, the current thread must own this object’s monitor.
Only one thread at a time can own an object’s monitor. |
|||||||
A thread becomes the owner of the object’s monitor in one of three ways:
|
|||||||
| wait()
notify() notifyAll() |
These are instance methods of the Object class. | ||||||
| wait()
wait(long) |
Every object has a list of thread that are waiting for signal related to the object monitor. | ||||||
| A thread gets on the list by executing the wait() method of the object. | |||||||
| public class Wait() {
public static void main(String arg) }{ synchronized(arg) { arg.wait(); } } } The thread is synchronized on the arg object. |
|||||||
| A thread waits on an object’s monitor by calling one of the wait methods. | |||||||
| Waits to be notified by another thread of a change in this object monitor. | |||||||
| When wait() is called, the thread releases ownership of this object monitor and waits until another thread notifies threads waiting on this object’s monitor to wake up. | |||||||
| Either through a call to the notify method or the notifyAll method.
The thread then waits until it can re-obtain ownership of the monitor and resumes execution. |
|||||||
| wait( long milliseconds)
wait(long, int) |
This wait method pauses for a time period. If the thread is not interrupted, it will continue normally.
Same as the wait(long), but waits an extra nanoseconds |
||||||
| If wait(2000) is called, another thread will get turn at the CPU by:
interrupting, notifying the thread, or two seconds have elapsed. |
|||||||
Execution will continue after
|
|||||||
| If the time as elapsed and no other thread has a lock on the object, the waiting thread will proceed. | |||||||
| public final native void notify() | Wakes up a single thread that is waiting on this object’s monitor.
This method should only be called by a thread that is the owner of this object’s monitor. |
||||||
| Exam Tip | When an object is waiting, another object must call its notify() method. | ||||||
| If many threads are blocked, only one will get out of the waiting list and proceed with its execution. | |||||||
| Like a sleeping thread, a waiting thread throw an InterruptedException when it is notified. | |||||||
| try {
wait(); } catch (InterruptedException){ } |
|||||||
| For a thread to call wait() or notify() it has to be the owner of the lock for that object. | |||||||
| When a thread calls the wait() method, the object temporarily releases the lock and is put on the waiting list. This gives other threads a chance to use the object – call notify(). But it will need the lock again to continue execution. | |||||||
| synchronize(this) { //Thread has lock at this point
try { wait(); //Lock released temporary //Lock is regained here } catch (InterruptedException){ } } The object waits until other thread call notify on this object. |
|||||||
| synchronize(this) {
notify() } This object notifies a thread waiting on this object. |
|||||||
| Exam Tip | If either wait() or notify() does not own the lock on the object, they will throw an IllegalMonitorStateException. | ||||||
| Exam Tip | IllegalMonitorStateException is not a checked exception it does not have to be caught. | ||||||
| Both wait() and notify should be in looping flow structure to recheck its state. | |||||||
| public final native void notifyAll() | Wakes up all threads that are waiting on this object’s monitor. An object may have many threads waiting on it, notify() affects only one.
|
||||||
| Exam Tip | If more than one thread is waiting, it can not be predicted or control which one notify() will take off the waiting list. | ||||||
| Using notifyAll(), all waiting threads will be notified and begin to compete for the object lock. | |||||||
| Be careful, all these threads with come out of their waiting state, but only one will get the lock. The threads what don’t get the lock must go back into a waiting state. Use a flag to reset them back. | |||||||
| If a thread that holds the object lock dies, the JVM removes the lock and does the equivalent of notifyAll for each object locked. | |||||||
| Deadlock | Deadlock occurs when thread get stuck for a while trying to get lock that another object owns, while it is holding a lock that the other object needs. Neither can get at the other’s lock they need.
Neither of the thread can proceed until some locked object is released.
This is a circular path of execution. |
||||||
| The simplest way to fix this problem is to rewrite the methods and swap the order of locking.
Keep it simple |
|||||||
| Scheduling | Getting a thread to perform reliably is an important consideration on many platform. | ||||||
| public static native void yield() | The thread static method can be used to allow a thread to specifically give other threads turn at the CPU. | ||||||
| Besides yielding, a current thread can give up processing by calling sleep(), wait() or blocked operations. | |||||||
| Exam Tip | Calling yield() on a reference to a thread makes the current thread yield(). | ||||||
| Blocked Thread | Blocking I/O operations are the ones that read/write information from a stream, and after some information arrives from the stream. | ||||||
| Time Slicing | In “time-slicing” systems, a thread is forcefully switch to another thread after a given period of time. | ||||||
| Thread Priorities | Thread can have priorities 1 through 10.
The intention of priorities is to suggest that no lower priority thread executes while a higher one is executing. |
||||||
| This is not guaranteed. | |||||||
| There are constants for thread MIN_PRIORITY (1) and MAX_PRIORITY (10), NORM_PRIORITY (5). | |||||||
| public final void setPriority(int p) | Changes the priority of this thread.
The priority of this thread is set to the smaller of the specified priority and the maximum permitted priority of the thread’s thread group. |
||||||
| First the checkAccess() method of this thread is called. This may result in throwing a the runtime exceptions SecurityException or an IllegalArgumentException if the priority argument is not between 1-10. | |||||||
| Exam Tip | A priority of a thread can change while it is running | ||||||
| The priority of a thread can not be changed when it is constructed. Use setPriority() method. | |||||||
| For most applications NORM_PRIORITY will be used. | |||||||
| Exam Tip | The priority of a thread can not be set on creation. But, it can implicitly get the priority of the threadgroup while creating it | ||||||
| Thread priority are changed after its creation by calling the setPriority() method. | |||||||
| The priority of a thread can not be changed based on the priority of the thread that calls it. The threadgroup affects the priority. | |||||||
| Exam Tip | The security manager can allow or disallows the setting of thread priority. | ||||||
| Exam Tip | The JVM determines what thread get access to the CPU.
A thread can not be forced to gain access to the CPU. |
||||||
| ThreadGroups | ThreadGroup manages group of threads.
A thread will always have a parent threadgroup. |
||||||
| Exam Tip | The threadgroup can be specified when the thread is constructed. | ||||||
| A ThreadGroup can belong to another ThreadGroup, except for the root one, which is created by the JVM. | |||||||
| Exam Tip | A thread can not surpass the priority of the ThreadGroup. | ||||||
| Thread Exit | System.exit( number ) can be used to forcefully end the JVM. But some clean up work maybe needed. | ||||||
| Detecting the InterruptedException or using interrupted() flag to text when a thread ends allows for graceful exit of a program and allow for various clean up. | |||||||
| However blocked I/O do not generate interrupt() signal or InterruptedException. In this case closing the underlying stream from a different thread is required. | |||||||
| Daemon Threads | Daemon threads are background threads. Daemon thread are used to service other threads. | ||||||
| Setting a thread to daemon thread is created by calling this method: | |||||||
| activethread.setDaemon(true); | |||||||
| When the JVM has only daemon threads running it exists. | |||||||
| Exam Tip | Daemon thread are automatically stopped. Programmers can’t stop them | ||||||
| Deprecated methods | As of Java 2.0 these methods have been deprecated. | ||||||
| suspend()
resume() |
Halt a thread and call resume to restart it.
A thread has lock on an object, it retains the lock while suspended. This will cause a deadlock on the object. |
||||||
| stop() | Stops a thread.
However stop() method may leave the thread in an inconsistent state.
An alternative is to used a flag variable in the run method and use the interrupt() method to stop it. |
||||||
| Exam Tip | In Java 2.0 they are a few static methods that are used: | ||||||
| Thread.yield()
Thread.sleep(#) Thread.interrupted() |
Needs try-catch block. |
||||||
| Exam Tip | In Java 2.0 they are several instance methods | ||||||
| Thread.start()
Thread.run() Thread.toString() Thread.interrupt() Thread.isInterrupted() |
|||||||
| Object.wait()
Object.wait(#) Object.notify() Object.notifyAll() |
Needs try-catch block | ||||||