For Java thread basic, please read this : http://codinglords.com/blog/getById/3
To have details about Immutability and thread safety concepts, please read this series : http://codinglords.com/blog/getById/54
This article will primarily cover multithreading concepts, and some best practices for concurrency in Java.
It is divided into 4 sections:
Basics
UncaughtExceptionHandling for Threads
Is DCL(double check locking) enough for Singletons ?
Java Memory Model
A thread is a lightweight process in Java, which executes in parallel to the invocation process. Each thread has its own stack (which is not shared across different threads). Threads are scheduled by the underlying operating system only, and JVM guides the behavior of os-level-threads.
A thread in java can have 5 different states:
- New : just created thread object.
- Runnable : after start() method, or resumed(), notified()
- Non-Runnable : suspended, sleeping, waiting
- Running
- Terminated : when run() exits
You can refer to http://codinglords.com/blog/getById/3 to know about various ways to create threads
A basic class invoking a thread :
public static void main(String[] args){
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
//some independent operation which can be done in parallel
System.out.println("Hello world from a thread !");
}
});
thread.start();
}
If run
method finishes, the thread ends naturally. If we want to know the status of a thread , isAlive() method returns true if the thread is still not terminated.
Thread Scheduling:
Each thread in java has a priority assigned from 1 to 10 (which we can change). The operating system decides which thread to run and when, and when to switch the threads and so on. But a high-priority thread can preempt a lower-priority thread at any time, and the operating system generally respects the priorities given.
You may have encountered a scenario where an unchecked exception is thrown from a code which is executed by a different thread.
package com.codinglords;
/**
* Created by naveensoni on 8/10/17.
*/
public class UncheckedException {
public static void main(String[] args) throws RuntimeException{
UncheckedException ue=new UncheckedException();
System.out.println("Test started");
ue.methodInvokedInDifferentThread();
System.out.println("Test finished");
}
public void methodInvokedInDifferentThread() throws RuntimeException{
// do something silly
throw new Exception("Thrown from the main thread");
}
}
In the above code is executed, we will get the following output:
Test started
Exception in thread "main" java.lang.Exception: Thrown from a separate thread
at com.codinglords.UncheckedException.methodInvokedInDifferentThread(UncheckedException.java:17)
at com.codinglords.UncheckedException.main(UncheckedException.java:11)
But, if the same method was invoked from a thread :
Then, the output would be:
Exception in thread "Thread-0" java.lang.RuntimeException: Thrown from the main thread
at com.codinglords.UncheckedException.methodInvokedInDifferentThread(UncheckedException.java:21)
at com.codinglords.UncheckedException.lambda$main$0(UncheckedException.java:12)
at java.lang.Thread.run(Thread.java:748)
Test finished
This time we were able to see Test finished, but why ?
Because in the first case, the exception was thrown back to the caller method, and eventually it reached main method. From main, we thrown it to JVM, and JVM crashed the program mentioning the exception.
But in the thread example, we exception was again sent back to original caller , which in this case was a thread only , And you can't throw any exception out of a thread by adding any throws clause. Because run() method's signature can't be changed. So , how to capture this exception ?
The Thread class provides a setUncaughtExceptionHandler
() method, which is capable of capturing exceptions thrown by this thread, As below :
package com.codinglords;
/**
* Created by naveensoni on 8/10/17.
*/
public class UncheckedException {
public static void main(String[] args) throws Exception{
UncheckedException ue=new UncheckedException();
System.out.println("Test started");
Thread t=new Thread(()->{
ue.methodInvokedInDifferentThread();
});
t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
System.out.println("Handling exception here");
}
});
t.start();
Thread.sleep(10000);
System.out.println("Test finished");
}
public void methodInvokedInDifferentThread() throws RuntimeException{
// do something silly
throw new RuntimeException("Thrown from the main thread");
}
}
Now the output becomes:
Test started
Handling exception here
Test finished
In this way, we can capture the uncaughtexceptions, thrown out in our thread.
WIP
WIP