- An instance of Java class java.lang.Thread
- Like every other objects in Java, Thread objects have variables and method, live and die at heap memory
- Thread of execution
- A lightweight process that has its own call stack
- Each thread a call stack or each call stack a thread
-
Extend the class java.lang.Thread and override the method
public void run()
/** * Created by tamnv on 1/8/18. */ public class SomeThread extends Thread { @Override public void run() { // New thead will execute code here } // The overloaded method public void run(String string) { } }
You can overload the run method but Thread class will ignore the overloaded method. Even if you call the overloaded run method directly, it will not start a new thread, it will execute the overloaded one in the thread that calls it.
-
Implement Runnable interface
/** * Created by tamnv on 1/8/18. */ public class SomeTask implements Runnable { @Override public void run() { // Code for a new thread here } public static void main(String[] args) { SomeTask task = new SomeTask(); Thread thread = new Thread(task); thread.start(); } }
Implement the Runnable interface will allow you to extend the class you like while accepting you define the behavior that will be run by a separate thread.
To start a thread you have to call thread.start();
. This method call will start a new call stack. To summarize, following are the things happen when you call thread start:
- A new thread of execution starts (with a new call stack)
- Thread moves from new state to runnable state
- When the thread has chance to run (by the thread scheduler), its target run method will run and thread moves to running state.
The behavior is not guaranteed
- Nothing guarantees that threads will start running in order they were started.
- There is no guarantee that once a thread starts executing it will execute until it's done.
- A thread done being a thread when its target
run()
method completes. - Once a thread has beed started, it can never be started again,
IllegalThreadStateException
will be thrown.
Thread Scheduler is the part of the JVM (although most of JVMs map Java theads directly to OS threads) that decides which thread should be run and which thread should be taken out of running state.
A thread can only be in one of five states:
- New, a thread is said in new state when an instance of java class Thread is created but not yet call
start()
method. In this point, it's a liveThread
object but not yet a thread of execution. It's considered not alive. - Runnable, when the method
start()
is called, the thread will moves torunnable
state. At this state, the thread will have chance to be picked up be Thread Scheduler to move torunning
state. But a thread can also return torunnable
state after enteringrunning
state or comming back fromblocked/waiting/sleeping
state. - Running, this is it, the big time when the code in the run method will be executed. The thread scheduler selects a thread from
runnable
pool to move it to staterunning
. - Waiting/Blocked/Sleeping, this is the state when a thread is not eligible to run. In other words, it's not runnable but it might return to runnable if a particular event occurs. A thread may be blocked waiting for a resource (such as IO or an object lock). A thread may be sleeping because the thread's run code tell it to sleep a period of time. A thread can be waiting because the thread's run code causes it to wait. The important point is that one thread does not tell the others to block.
- Dead, a thread is called dead when the run method completes.
Interrupt is an indication to a thread that it should stop what it is doning and do something else. It's up to programmer to decide how a thread responds to an interrupt but the common way is to terminate the execution (return from run). A thread send an interrupt to other thread by invoking the interrupt()
method of that other thread instance. For the interrupt mechanism woriking correctly the interrupted thread must support its own interruption.
-
Supporting interruption, how does a thread support its own interruption? It depends on what the thread is doing.
- If the thread is invoking some methods that can throw
InterruptedException
(like sleep method), it should simply return from run method after catching that exception.// I am doing something and need to take a rest by sleeping to wait for something try { Thread.sleep(60 * 1000); // Try to sleep 1 minute } catch (InterruptedException e) { // But someone (other thread) does not want me to sleep, he/she interrupt my dream by sending an interrupt // I have not slept full 1 minute and have to wake up and quit the execution return; }
- If the thread is not invoking methods that can throw
InterruptedException
, it should frequently check if it is interrupted and return from run method.while (!queue.isEmpty()) { handleMessage(queue.get()); if (Thread.interrupted()) { // I am handling messages someone sends me, but the other one want to intterupt me, tell me to quit this job return; } }
- If the thread is invoking some methods that can throw
-
The Interrupt Status Flag, invoking
Thread.interrupt()
sets the interrupted status/flag of the target thread.
The sleep()
method is a static method of class java.lang.Thread
. It is used to force the current thread (important: current thread, no thread can tell others to sleep) to go to sleeping
state. When a thread sleeps, it does not return runnable state until it wakes up. Notice that, the sleep method can throw checked InteruptedException.
try {
Thread.sleep(60 * 1000); // Sleep 60 seconds
} catch (InteruptedException e) {
// I am sleeping and is interrupted by someone so I have to wake up!
// Meaning I can not complete the sleep for 60 seconds
}
When an InteruptedException is thrown? When it's interupted before it's wake up time.
Remember sleep()
method is a static method of class java.lang.Thread
so don't be fool thinking that one thread can put another thread to sleep.
yield()
is a static method. What yield()
supposed to do is move thread from running state to runnable pool to make other threads have chance to be selected by scheduler. But again, yield does not guarantee other threads will be selected, it only guarantee one thing, move current thread from running to runnable.
Notice that, yield is almost not helpful in practial, rarely used in practical.
If you are in thread B and you want thread A finish its job (enter dead state) so you can start your job, you can invoke a.join()
to wait. Once you invoke a.join()
you (thread B) will be blocked and cannot going to runnable state before thread A is done.
// You are in the thread B here
// You want thread A to do something for you so that you can start your job in thread B
Thread a;
a.start();
// You must invoke a.join() to wait for thread A to be done.
a.join();
// Once thread A done its job, you can start your job
startMyJob();
I have a repository [Concurrency] for synchronization. Here I just want to clarify my understanding on wait()
, notify()
and notifyAll()
. One key point to remember (and keep it stuck in your mind) about wait/notify is this:
-
wait(), notify(), notifyAll() must be called in context of synchronized. Meaning a thread cannot invoke wait/notify method on an object if it does not own that object's lock (monitor).
-
wait()
method lets a thread says, there is nothing for me to do now, so put me in the waiting pool and notify me when something happens that I care about. Basically, await()
call meaning let me wait in the pool or add me to the waiting list.wait()
invocation will release the lock.wait()
has to be called in a loop due to spurious wake-up. -
notify()
method is used to send a signal to one and only one of the threads that are waiting on the same object's waiting pool.notify()
CANNOT specify which waiting thread to notify.notify()
DOES NOT release the lock. -
notifyAll()
works in the same ways asnotify()
, only it sends the signal to ALL threads that are waiting on the object. This invoke will let all the waiting threads start a race to aquire the lock of object to continue doing their job.notifyAll()
DOES NOT release the lock.
- When does a thread escape the
running
state? - What is the Race Condition?
- What is the Critical Section?
- What is the Synchronization and how to synchronize in Java?
- Differences between
synchronized method
andsynchronized block
? Which is preferred to use?