Thread
1) Thread
(a) Thread Basic
(b) DeadLock conditions
(c) Synchronization
2) JVM, JDK,JRE
3) General Java Question(Final, static, Abstract)
4) Design Pattern
(a) Singleton
(b) Factory Design pattern
(c) Abstract Factory Design pattern
5) Serialization
volatile Java variable
Declaring a volatile Java variable means: The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory"; Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself.
Important points on Volatile keyword in Java
1. The volatile keyword in Java is only application to a variable and using volatile keyword with class and method is illegal.
2. volatile keyword in Java guarantees that value of the volatile variable will always be read from main memory and not from Thread's local cache.
3. In Java reads and writes are atomic for all variables declared using Java volatile keyword (including long and double variables).
4. Using the volatile keyword in Java on variables reduces the risk of memory consistency errors because any write to a volatile variable in Java establishes a happens-before relationship with subsequent reads of that same variable.
5. From Java 5 changes to a volatile variable are always visible to other threads. What's more, it also means that when a thread reads a volatile variable in Java, it sees not just the latest change to the volatile variable but also the side effects of the code that led up the change.
6. Reads and writes are atomic for reference variables are for most primitive variables (all types except long and double) even without the use of volatile keyword in Java.
7. An access to a volatile variable in Java never has a chance to block, since we are only doing a simple read or write, so unlike a synchronized block we will never hold on to any lock or wait for any lock.
8. Java volatile variable that is an object reference may be null.
9. Java volatile keyword doesn't mean atomic, its common misconception that after declaring volatile ++ will be atomic, to make the operation atomic you still need to ensure exclusive access using synchronized method or block in Java.
10. If a variable is not shared between multiple threads, you don't need to use volatile keyword with that variable.
2. volatile keyword in Java guarantees that value of the volatile variable will always be read from main memory and not from Thread's local cache.
3. In Java reads and writes are atomic for all variables declared using Java volatile keyword (including long and double variables).
4. Using the volatile keyword in Java on variables reduces the risk of memory consistency errors because any write to a volatile variable in Java establishes a happens-before relationship with subsequent reads of that same variable.
5. From Java 5 changes to a volatile variable are always visible to other threads. What's more, it also means that when a thread reads a volatile variable in Java, it sees not just the latest change to the volatile variable but also the side effects of the code that led up the change.
6. Reads and writes are atomic for reference variables are for most primitive variables (all types except long and double) even without the use of volatile keyword in Java.
7. An access to a volatile variable in Java never has a chance to block, since we are only doing a simple read or write, so unlike a synchronized block we will never hold on to any lock or wait for any lock.
8. Java volatile variable that is an object reference may be null.
9. Java volatile keyword doesn't mean atomic, its common misconception that after declaring volatile ++ will be atomic, to make the operation atomic you still need to ensure exclusive access using synchronized method or block in Java.
10. If a variable is not shared between multiple threads, you don't need to use volatile keyword with that variable.
Java Threads Examples
- Threading is a facility to allow multiple tasks to run concurrently within a single process. Threads are independent, concurrent execution through a program, and each thread has its own stack.
- In Java threads can be implemented in two ways. One is by 'Extending Thread Class' and the other way is by 'Implementing Runnable Interface'
- Extending Thread Class is required to 'override run()' method. The run method contains the actual logic to be executed by thread.
- Creation of thread object never starts execution, we need to call 'start()' method to run a thread. Examples gives you more details. Other methods supported by Threads are given below.
- join(): It makes to wait for this thread to die. You can wait for a thread to finish by calling its join() method.
- sleep(): It makes current executing thread to sleep for a specified interval of time. Time is in milli seconds.
- yield(): It makes current executing thread object to pause temporarily and gives control to other thread to execute.
- notify(): This method is inherited from Object class. This method wakes up a single thread that is waiting on this object's monitor to acquire lock.
- notifyAll(): This method is inherited from Object class. This method wakes up all threads that are waiting on this object's monitor to acquire lock.
- wait(): This method is inherited from Object class. This method makes current thread to wait until another thread invokes the notify() or the notifyAll() for this object.
1.3 Life Cycle of a Thread:
A thread goes through various stages in its life cycle. For example, a thread is born, started, runs, and then dies. Following diagram shows complete life cycle of a thread.
Above-mentioned stages are explained here:
· New: A new thread begins its life cycle in the new state. It remains in this state until the program starts the thread. It is also referred to as a born thread.
· Runnable: After a newly born thread is started, the thread becomes runnable. A thread in this state is considered to be executing its task.
· Waiting: Sometimes, a thread transitions to the waiting state while the thread waits for another thread to perform a task.A thread transitions back to the runnable state only when another thread signals the waiting thread to continue executing.
· Timed waiting: A runnable thread can enter the timed waiting state for a specified interval of time. A thread in this state transitions back to the runnable state when that time interval expires or when the event it is waiting for occurs.
· Terminated ( Dead ): A runnable thread enters the terminated state when it completes its task or otherwise terminates.
Thread Priorities:
Every Java thread has a priority that helps the operating system determine the order in which threads are scheduled.
Java thread priorities are in the range between MIN_PRIORITY (a constant of 1) and MAX_PRIORITY (a constant of 10). By default, every thread is given priority NORM_PRIORITY (a constant of 5).
Threads with higher priority are more important to a program and should be allocated processor time before lower-priority threads. However, thread priorities cannot guarantee the order in which threads execute and very much platform dependent.
Create Thread by Implementing Runnable Interface:
If your class is intended to be executed as a thread then you can achieve this by implementing Runnable interface. You will need to follow three basic steps:
Step 1:
As a first step you need to implement a run() method provided by Runnableinterface. This method provides entry point for the thread and you will put you complete business logic inside this method. Following is simple syntax of run() method:
publicvoid run()
1.3.1 Step 2:
At second step you will instantiate a Thread object using the following constructor:
Thread(RunnablethreadObj,StringthreadName);
Where, threadObj is an instance of a class that implements the Runnableinterface and threadName is the name given to the new thread.
1.3.2 Step 3
Once Thread object is created, you can start it by calling start( ) method, which executes a call to run( ) method. Following is simple syntax of start() method:
void start();
Example:
Here is an example that creates a new thread and starts it running:
classRunnableDemoimplementsRunnable{
privateThread t;
privateStringthreadName;
RunnableDemo(String name){
threadName= name;
System.out.println("Creating "+threadName);
}
publicvoid run(){
System.out.println("Running "+threadName);
try{
for(inti=4;i>0;i--){
System.out.println("Thread: "+threadName+", "+i);
// Let the thread sleep for a while.
Thread.sleep(50);
}
}catch(InterruptedException e){
System.out.println("Thread "+threadName+" interrupted.");
}
System.out.println("Thread "+threadName+" exiting.");
}
publicvoid start ()
{
System.out.println("Starting "+threadName);
if(t ==null)
{
t =newThread(this,threadName);
t.start();
}
}
}
publicclassTestThread{
publicstaticvoid main(Stringargs[]){
RunnableDemo R1 =newRunnableDemo("Thread-1");
R1.start();
RunnableDemo R2 =newRunnableDemo("Thread-2");
R2.start();
}
}
This would produce the following result:
CreatingThread-1
StartingThread-1
CreatingThread-2
StartingThread-2
RunningThread-1
Thread:Thread-1,4
RunningThread-2
Thread:Thread-2,4
Thread:Thread-1,3
Thread:Thread-2,3
Thread:Thread-1,2
Thread:Thread-2,2
Thread:Thread-1,1
Thread:Thread-2,1
ThreadThread-1 exiting.
ThreadThread-2 exiting.
Create Thread by Extending Thread Class:
The second way to create a thread is to create a new class that extendsThread class using the following two simple steps. This approach provides more flexibility in handling multiple threads created using available methods in Thread class.
Step 1
You will need to override run( ) method available in Thread class. This method provides entry point for the thread and you will put you complete business logic inside this method. Following is simple syntax of run() method:
publicvoid run()
Step 2
Once Thread object is created, you can start it by calling start( ) method, which executes a call to run( ) method. Following is simple syntax of start() method:
void start();
Example:
Here is the preceding program rewritten to extend Thread:
classThreadDemoextendsThread{
privateThread t;
privateStringthreadName;
ThreadDemo(String name){
threadName= name;
System.out.println("Creating "+threadName);
}
publicvoid run(){
System.out.println("Running "+threadName);
try{
for(inti=4;i>0;i--){
System.out.println("Thread: "+threadName+", "+i);
// Let the thread sleep for a while.
Thread.sleep(50);
}
}catch(InterruptedException e){
System.out.println("Thread "+threadName+" interrupted.");
}
System.out.println("Thread "+threadName+" exiting.");
}
publicvoid start ()
{
System.out.println("Starting "+threadName);
if(t ==null)
{
t =newThread(this,threadName);
t.start();
}
}
}
publicclassTestThread{
publicstaticvoid main(Stringargs[]){
ThreadDemo T1 =newThreadDemo("Thread-1");
T1.start();
ThreadDemo T2 =newThreadDemo("Thread-2");
T2.start();
}
}
This would produce the following result:
CreatingThread-1
StartingThread-1
CreatingThread-2
StartingThread-2
RunningThread-1
Thread:Thread-1,4
RunningThread-2
Thread:Thread-2,4
Thread:Thread-1,3
Thread:Thread-2,3
Thread:Thread-1,2
Thread:Thread-2,2
Thread:Thread-1,1
Thread:Thread-2,1
ThreadThread-1 exiting.
ThreadThread-2 exiting.
Thread Methods:
Following is the list of important methods available in the Thread class.
SN
|
Methods with Description
|
1
|
public void start()
Starts the thread in a separate path of execution, then invokes the run() method on this Thread object.
|
2
|
public void run()
If this Thread object was instantiated using a separate Runnable target, the run() method is invoked on that Runnable
object.
|
3
|
public final void setName(String name)
Changes the name of the Thread object. There is also a getName() method for retrieving the name.
|
4
|
public final void setPriority(int priority)
Sets the priority of this Thread object. The possible values are between 1 and 10.
|
5
|
public final void setDaemon(boolean on)
A parameter of true denotes this Thread as a daemon thread.
|
6
|
public final void join(long millisec)
The current thread invokes this method on a second thread, causing the current thread to block until the second thread terminates or the specified number of milliseconds passes.
|
7
|
public void interrupt()
Interrupts this thread, causing it to continue execution if it was blocked for any reason.
|
8
|
public final booleanisAlive()
Returns true if the thread is alive, which is any time after the thread has been started but before it runs to completion.
|
The previous methods are invoked on a particular Thread object. The following methods in the Thread class are static. Invoking one of the static methods performs the operation on the currently running thread.
SN
|
Methods with Description
|
1
|
public static void yield()
Causes the currently running thread to yield to any other threads of the same priority that are waiting to be scheduled.
|
2
|
public static void sleep(long millisec)
Causes the currently running thread to block for at least the specified number of milliseconds.
|
3
|
public static booleanholdsLock(Object x)
Returns true if the current thread holds the lock on the given Object.
|
4
|
public static Thread currentThread()
Returns a reference to the currently running thread, which is the thread that invokes this method.
|
5
|
public static void dumpStack()
Prints the stack trace for the currently running thread, which is useful when debugging a multithreaded application.
|
Example:
The following ThreadClassDemo program demonstrates some of these methods of the Thread class. Consider a class DisplayMessage which implementsRunnable:
// File Name : DisplayMessage.java
// Create a thread to implement Runnable
publicclassDisplayMessageimplementsRunnable
{
privateString message;
publicDisplayMessage(String message)
{
this.message= message;
}
public void run()
{
while(true)
{
System.out.println(message);
}
}
}
Following is another class which extends Thread class:
// File Name : GuessANumber.java
// Create a thread to extentd Thread
public class GuessANumber extends Thread
{
private int number;
public GuessANumber(int number)
{
this.number= number;
}
public void run()
{
int counter =0;
int guess =0;
do
{
guess=(int)(Math.random()*100+1);
System.out.println(this.getName()
+" guesses "+ guess);
counter++;
}while(guess != number);
System.out.println("** Correct! "+this.getName()
+" in "+ counter +" guesses.**");
}
}
Following is the main program which makes use of above defined classes:
// File Name : ThreadClassDemo.java
public class ThreadClassDemo
{
public static void main(String[]args)
{
Runnable hello =newDisplayMessage("Hello");
Thread thread1 =newThread(hello);
thread1.setDaemon(true);
thread1.setName("hello");
System.out.println("Starting hello thread...");
thread1.start();
Runnable bye =newDisplayMessage("Goodbye");
Thread thread2 =newThread(bye);
thread2.setPriority(Thread.MIN_PRIORITY);
thread2.setDaemon(true);
System.out.println("Starting goodbye thread...");
thread2.start();
System.out.println("Starting thread3...");
Thread thread3 =newGuessANumber(27);
thread3.start();
try
{
thread3.join();
}catch(InterruptedException e)
{
System.out.println("Thread interrupted.");
}
System.out.println("Starting thread4...");
Thread thread4 =newGuessANumber(75);
thread4.start();
System.out.println("main() is ending...");
}
}
This would produce the following result. You can try this example again and again and you would get different result every time.
Starting hello thread...
Starting goodbye thread...
Hello
Hello
Hello
Hello
Hello
Hello
Goodbye
Goodbye
Goodbye
Goodbye
Goodbye
.......
Major Java Multithreading Concepts:
While doing Multithreading programming in Java, you would need to have the following concepts very handy:
Can we start a thread twice
No. After starting a thread, it can never be started again. If you does so, an IllegalThreadStateException is thrown. In such case, thread will run once but for second time, it will throw exception.
Let's understand it by the example given below:
1.
public class TestThreadTwice1 extends Thread{
public class TestThreadTwice1 extends Thread{
2. public void run(){
3. System.out.println("running...");
4. }
5. public static void main(String args[]){
6. TestThreadTwice1 t1=new TestThreadTwice1();
7. t1.start();
8. t1.start();
9. }
10. }
running
Exception in thread "main" java.lang.IllegalThreadStateException
----------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------
Synchronization in Java
Synchronization in java is the capability to control the access of multiple threads to any shared resource.
Java Synchronization is better option where we want to allow only one thread to access the shared resource.
Why use Synchronization
The synchronization is mainly used to
- To prevent thread interference.
- To prevent consistency problem.
Types of Synchronization
There are two types of synchronization
- Process Synchronization
- Thread Synchronization
Here, we will discuss only thread synchronization.
Thread Synchronization
There are two types of thread synchronization mutual exclusive and inter-thread communication.
- Mutual Exclusive
- Synchronized method.
- Synchronized block.
- static synchronization.
- Cooperation (Inter-thread communication in java)
Mutual Exclusive
Mutual Exclusive helps keep threads from interfering with one another while sharing data. This can be done by three ways in java:
- by synchronized method
- by synchronized block
- by static synchronization
Concept of Lock in Java
Synchronization is built around an internal entity known as the lock or monitor. Every object has an lock associated with it. By convention, a thread that needs consistent access to an object's fields has to acquire the object's lock before accessing them, and then release the lock when it's done with them.
From Java 5 the package java.util.concurrent.locks contains several lock implementations.
Understanding the problem without Synchronization
In this example, there is no synchronization, so output is inconsistent. Let's see the example:
1. Class Table{
2.
3. void printTable(int n){//method not synchronized
4. for(int i=1;i<=5;i++){
5. System.out.println(n*i);
6. try{
7. Thread.sleep(400);
8. }catch(Exception e){System.out.println(e);}
9. }
10. }
11. }
12.
13. class MyThread1 extends Thread{
14. Table t;
15. MyThread1(Table t){
16. this.t=t;
17. }
18. public void run(){
19. t.printTable(5);
20. }
21.
22. }
23. class MyThread2 extends Thread{
24. Table t;
25. MyThread2(Table t){
26. this.t=t;
27. }
28. public void run(){
29. t.printTable(100);
30. }
31. }
32.
33. class TestSynchronization1{
34. public static void main(String args[]){
35. Table obj = new Table();//only one object
36. MyThread1 t1=new MyThread1(obj);
37. MyThread2 t2=new MyThread2(obj);
38. t1.start();
39. t2.start();
40. }
41. }
Output: 5
100
10
200
15
300
20
400
25
500
Java synchronized method
If you declare any method as synchronized, it is known as synchronized method.
Synchronized method is used to lock an object for any shared resource.
When a thread invokes a synchronized method, it automatically acquires the lock for that object and releases it when the thread completes its task.
1. //example of java synchronized method
2. class Table{
3. synchronized void printTable(int n){//synchronized method
4. for(int i=1;i<=5;i++){
5. System.out.println(n*i);
6. try{
7. Thread.sleep(400);
8. }catch(Exception e){System.out.println(e);}
9. }
10.
11. }
12. }
13.
14. class MyThread1 extends Thread{
15. Table t;
16. MyThread1(Table t){
17. this.t=t;
18. }
19. public void run(){
20. t.printTable(5);
21. }
22.
23. }
24. class MyThread2 extends Thread{
25. Table t;
26. MyThread2(Table t){
27. this.t=t;
28. }
29. public void run(){
30. t.printTable(100);
31. }
32. }
33.
34. public class TestSynchronization2{
35. public static void main(String args[]){
36. Table obj = new Table();//only one object
37. MyThread1 t1=new MyThread1(obj);
38. MyThread2 t2=new MyThread2(obj);
39. t1.start();
40. t2.start();
41. }
42. }
Output: 5
10
15
20
25
100
200
300
400
500
Example of synchronized method by using annonymous class
In this program, we have created the two threads by annonymous class, so less coding is required.
1. //Program of synchronized method by using annonymous class
2. class Table{
3. synchronized void printTable(int n){//synchronized method
4. for(int i=1;i<=5;i++){
5. System.out.println(n*i);
6. try{
7. Thread.sleep(400);
8. }catch(Exception e){System.out.println(e);}
9. }
10.
11. }
12. }
13.
14. public class TestSynchronization3{
15. public static void main(String args[]){
16. final Table obj = new Table();//only one object
17.
18. Thread t1=new Thread(){
19. public void run(){
20. obj.printTable(5);
21. }
22. };
23. Thread t2=new Thread(){
24. public void run(){
25. obj.printTable(100);
26. }
27. };
28.
29. t1.start();
30. t2.start();
31. }
32. }
Output: 5
10
15
20
25
100
200
300
400
500
------------------------------------------------------------------------------------
Synchronization Block, Synchronization Method and static Synchronization with examples
-------------------------------------------------------------------------------------
Difference between wait and sleep?
Let's see the important differences between wait and sleep methods.
wait()
|
sleep()
|
wait() method releases the lock
|
sleep() method doesn't release the lock.
|
is the method of Object class
|
is the method of Thread class
|
is the non-static method
|
is the static method
|
should be notified by notify() or notifyAll() methods
|
after the specified amount of time,
sleep is completed.
|
Concept behind putting wait(),notify() methods in Object class [duplicate]
I am just having hard time to understand concept behind putting wait() in object class For this questions sake consider as if wait() and notifyAll() are in thread class
In the Java language, you
wait()
on a particular instance of an Object
– a monitor assigned to that object to be precise. If you want to send a signal to one thread that is waiting on that specific object instance then you call notify()
on that object. If you want to send a signal to all threads that are waiting on that object instance, you use notifyAll()
on that object.
If
wait()
and notify()
were on the Thread
instead then each thread would have to know the status of every other thread. How would thread1 know that thread2 was waiting for access to a particular resource? If thread1 needed to call thread2.notify()
it would have to somehow find out that thread2
was waiting. There would need to be some mechanism for threads to register the resources or actions that they need so others could signal them when stuff was ready or available.
In Java, the object itself is the entity that is shared between threads which allows them to communicate with each other. The threads have no specific knowledge of each other and they can run asynchronously. They run and they lock, wait, and notify on the object that they want to get access to. They have no knowledge of other threads and don't need to know their status. They don't need to know that it is thread2 which is waiting for the resource – they just notify on the resource and whomever it is that is waiting (if anyone) will be notified.
In Java, we then use lock objects as synchronization, mutex, and communication points between threads. We synchronize on a lock object to get mutex access to an important code block and to synchronize memory. We wait on an object if we are waiting for some condition to change – some resource to become available. We notify on an object if we want to awaken sleeping threads.
// locks should be final objects so the object instance we are synchronizing on,
// never changes
private final Object lock = new Object();
...
// ensure that the thread has a mutex lock on some key code
synchronized (lock) {
...
// i need to wait for other threads to finish with some resource
// this releases the lock and waits on the associated monitor
lock.wait();
...
// i need to signal another thread that some state has changed and they can
// awake and continue to run
lock.notify();
}
There can be any number of lock objects in your program – each locking a particular resource or code segment. You might have 100 lock objects and only 4 threads. As the threads run the various parts of the program, they get exclusive access to one of the lock objects. Again, they don't have to know the running status of the other threads.
This allows you to scale up or down the number of threads running in your software as much as you want. You find that the 4 threads is blocking too much on outside resources, then you can increase the number. Pushing your battered server too hard then reduce the number of running threads. The lock objects ensure mutex and communication between the threads independent on how many threads are running.
package com.Thread;
class Process implements Runnable{
@Override
public void run() {
int arr[] ={1,2,3,4,5,6};
for(int i=0; i<arr.length;i++){
System.out.println("Numbers :" + arr[i]);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class ThreadTest {
public static void main(String[] args) {
System.out.println("Ali");
Thread th_1 = new Thread(new Process());
th_1.start();
Thread th_2 = new Thread(new Process());
th_2.start();
}
}
OUTPUT:-
Ali
Numbers :1
Numbers :1
Numbers :2
Numbers :2
Numbers :3
Numbers :3
Numbers :4
Numbers :4
Numbers :5
Numbers :5
Numbers :6
Numbers :6
New Thread Class
package com.Thread;
class ThreadClass_A extends Thread {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("Thread Name :" + currentThread() + " " + i);
}
}
}
public class ThreadClassTest {
public static void main(String[] args) {
ThreadClass_A tca = new ThreadClass_A();
tca.start();
try {
tca.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 5; i++) {
System.out.println("T Count "+ i);
}
}
}
OUTPUT:-
Thread Name :Thread[Thread-0,5,main] 0
Thread Name :Thread[Thread-0,5,main] 1
Thread Name :Thread[Thread-0,5,main] 2
Thread Name :Thread[Thread-0,5,main] 3
Thread Name :Thread[Thread-0,5,main] 4
T Count 0
T Count 1
T Count 2
T Count 3
T Count 4
New Class with Thread and Runnable()
package com.Thread;
public class ThreadRunnable {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable(){
@Override
public void run() {
for(int i=0; i<5; i++){
System.out.println("Thread : "+ i);
}
}
});
thread.start();
}
}
OUTPUT:-
Thread : 0
Thread : 1
Thread : 2
Thread : 3
Thread : 4
Thread Sleep
try {
Thread.sleep(5*60*1000); // Sleep for 5 minutes
} catch (InterruptedException ex) { }
Notice:- that the sleep() method can throw a checked InterruptedException
(you'll usually know if that is a possibility, since another thread has to explicitly do
the interrupting), so you must acknowledge the exception with a handle or declare.
Typically, you wrap calls to sleep() in a try/catch, as in the preceding code
One Thread Print number’s of Array and another thread Print sum of that elements of Array
package com.Thread;
public class ThreadTest_Array {
public static void main(String[] args) {
int arr[] = { 1, 2, 3, 4, 5 };
Thread thread_1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < arr.length; i++) {
System.out.println("Element in array : " + arr[i]);
}
}
});
Thread thread_2 = new Thread(new Runnable() {
@Override
public void run() {
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum = sum + arr[i];
}
System.out.println("Sum of elements in array : " + sum);
}
});
thread_1.start();
thread_2.start();
try {
thread_2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
OUTPUT:-
Sum of elements in array : 15
Element in array : 1
Element in array : 2
Element in array : 3
Element in array : 4
Element in array : 5
Array read half element of Array and another thread read half part of array
package com.Thread;
public class HalfElementOfArrayOneThread {
public static void main(String[] args) {
int arr[] = {1,2,3,4,5,6};
Thread thread_1 = new Thread(new Runnable(){
@Override
public void run() {
for(int i=0;i<arr.length/2; i++){
System.out.println("Element of Array-1 :"+ arr[i]);
}
SysSystem.out.println("---------------------");------");
}
});
Thread thread_2 = new Thread(new Runnable(){
@Override
public void run() {
for(int i=arr.length/2 ;i<arr.length; i++){
System.out.println("Element of Array-2 :"+ arr[i]);
}
}
});
thread_1.start();
try {
thread_1.join();
//thread_2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
thread_2.start();
}
}
OUTPUT:-
Element of Array-1 :1
Element of Array-1 :2
Element of Array-1 :3
---------------------
Element of Array-2 :4
Element of Array-2 :5
Element of Array-2 :6
-------------------------------------------------------------------------------------
AtomicInteger
Atomic class youTubeThis is an example of how to use the
AtomicInteger
class of Java. The java.util.concurrent.atomic package provides very useful classes that support lock-free and thread-safe programming on single variables. Among them, the AtomicInteger
class is a wrapper class for an int
value that allows it to be updated atomically. The class provides useful methods, some of which will be shown in the code snippet below.
The most common use of the
AtomicInteger
is to handle a counter that is accessed by different threads simultaneously. In order to see how this works, we will create and run two Threads
, each one of which will access and update an AtomicInteger
variable, using its API methods. The basic methods used in the example are described in short:- With
incrementAndGet()
API method, the value is incremented and its new value is returned. - With
getAndIncrement()
API method, the value is incremented, but its previous value is returned. - With
addAndGet(int delta)
API method, thedelta
is added to the value and the new value is returned, whereas there is also agetAndAdd(int delta)
method that adds thedelta
to the value, but returns the previous value. - With
compareAndSet(int expect, int update)
API method, the value is compared to theexpect
param, and if they are equal, then the value is set to theupdate
param andtrue
is returned. - You can get the
int
,long
,float
ordouble
value of theAtomicInteger
variable, usingintValue()
,longValue()
,floatValue()
anddoubleValue()
methods respectivelly.
AtomicIntegerExample.java
01 | package com.javacodegeeks.snippets.core; |
02 |
03 | import java.util.concurrent.atomic.AtomicInteger; |
04 |
05 | public class AtomicIntegerExample { |
06 |
07 | private static AtomicInteger at = new AtomicInteger( 0 ); |
08 |
09 | static class MyRunnable implements Runnable { |
10 |
11 | private int myCounter; |
12 | private int myPrevCounter; |
13 | private int myCounterPlusFive; |
14 | private boolean isNine; |
15 |
16 | public void run() { |
17 | myCounter = at.incrementAndGet(); |
18 | System.out.println( "Thread " + Thread.currentThread().getId() + " / Counter : " + myCounter); |
19 | myPrevCounter = at.getAndIncrement(); |
20 | System.out.println( "Thread " + Thread.currentThread().getId() + " / Previous : " + myPrevCounter); |
21 | myCounterPlusFive = at.addAndGet( 5 ); |
22 | System.out.println( "Thread " + Thread.currentThread().getId() + " / plus five : " + myCounterPlusFive); |
23 | isNine = at.compareAndSet( 9 , 3 ); |
24 | if (isNine) { |
25 | System.out.println( "Thread " + Thread.currentThread().getId() |
26 | + " / Value was equal to 9, so it was updated to " + at.intValue()); |
27 | } |
28 |
29 | } |
30 | } |
31 |
32 | public static void main(String[] args) { |
33 | Thread t1 = new Thread( new MyRunnable()); |
34 | Thread t2 = new Thread( new MyRunnable()); |
35 | t1.start(); |
36 | t2.start(); |
37 | } |
38 | } |
If you run the example, you will see that both threads can update the
AtomicInteger
variable atomically.
Output
1 | Thread 9 / Counter : 1 |
2 | Thread 10 / Counter : 2 |
3 | Thread 9 / Previous : 2 |
4 | Thread 9 / plus five : 9 |
5 | Thread 9 / Value was equal to 9, so it was updated to 3 |
6 | Thread 10 / Previous : 3 |
7 | Thread 10 / plus five : 8
|
------------------------------------------------------------------------------------------------------------
import java.util.concurrent.atomic.AtomicInteger;
class TestA{
public static int variable = 0;
public static AtomicInteger atomicVar = new AtomicInteger(0);
}
public class VariableSynchronizedTest extends Thread{
public void run(){
/*synchronized (TestA.class) {
TestA testA = new TestA();
testA.variable++;
System.out.print(testA.variable + " ");
}*/
TestA testA = new TestA();
System.out.print(testA.atomicVar.getAndIncrement()+" ");
}
public static void main(String[] args) {
for(int i=0; i<250; i++){
Thread thread_1 = new VariableSynchronizedTest();
thread_1.start();
}
}
}
OUTPUT:-
0 4 3 2 1 5 6 7 8 9 10 12 11 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 38 37 39 40 41 42 43 44 45 46 47 48 50 49 51 52 53 54 55 56 57 58 59 60 61 62 63 65 64 67 66 69 68 70 71 72 73 74 75 76 77 78 79 80 81 82 84 83 85 86 87 88 89 90 91 92 93 94 95 96 97 98 100 101 103 104 99 102 106 105 107 108 109 111 110 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 138 137 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 221 220 222 223 224 225 227 226 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
---------------------------------------------------------------------------------
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
class AtomicCheck implements Runnable {
public AtomicInteger number = new AtomicInteger();
private AtomicBoolean atomicBoolean = new AtomicBoolean();
@Override
public void run() {
number.set(123);
atomicBoolean.set(true);
System.out.println(number);
System.out.println(number.incrementAndGet());
System.out.println(atomicBoolean);
}
}
public class TaskAtomic {
public static void main(String args[]) {
AtomicCheck ac = new AtomicCheck();
Thread thread = new Thread(ac);
thread.start();
}
}
OUTPUT:-
123
124
true
------------------------------------------------------------------------------
Thread Pools
Thread Pools are useful when you need to limit the number of threads running in your application at the same time. There is a performance overhead associated with starting a new thread, and each thread is also allocated some memory for its stack etc.
Instead of starting a new thread for every task to execute concurrently, the task can be passed to a thread pool. As soon as the pool has any idle threads the task is assigned to one of them and executed. Internally the tasks are inserted into a Blocking Queue which the threads in the pool are dequeuing from. When a new task is inserted into the queue one of the idle threads will dequeue it successfully and execute it. The rest of the idle threads in the pool will be blocked waiting to dequeue tasks.
Thread pools are often used in multi threaded servers. Each connection arriving at the server via the network is wrapped as a task and passed on to a thread pool. The threads in the thread pool will process the requests on the connections concurrently. A later trail will get into detail about implementing multithreaded servers in Java.
Java 5 comes with built in thread pools in the
java.util.concurrent
package, so you don't have to implement your own thread pool. You can read more about it in my text on the java.util.concurrent.ExecutorService. Still it can be useful to know a bit about the implementation of a thread pool anyways.
Here is a simple thread pool implementation. Please note that this implementation uses my own
BlockingQueue
class as explained in my Blocking Queues tutorial. In a real life implementation you would probably use one of Java's built-in blocking queues instead.public class ThreadPool {
private BlockingQueue taskQueue = null;
private List<PoolThread> threads = new ArrayList<PoolThread>();
private boolean isStopped = false;
public ThreadPool(int noOfThreads, int maxNoOfTasks){
taskQueue = new BlockingQueue(maxNoOfTasks);
for(int i=0; i<noOfThreads; i++){
threads.add(new PoolThread(taskQueue));
}
for(PoolThread thread : threads){
thread.start();
}
}
public synchronized void execute(Runnable task) throws Exception{
if(this.isStopped) throw
new IllegalStateException("ThreadPool is stopped");
this.taskQueue.enqueue(task);
}
public synchronized void stop(){
this.isStopped = true;
for(PoolThread thread : threads){
thread.doStop();
}
}
}
public class PoolThread extends Thread {
private BlockingQueue taskQueue = null;
private boolean isStopped = false;
public PoolThread(BlockingQueue queue){
taskQueue = queue;
}
public void run(){
while(!isStopped()){
try{
Runnable runnable = (Runnable) taskQueue.dequeue();
runnable.run();
} catch(Exception e){
//log or otherwise report exception,
//but keep pool thread alive.
}
}
}
public synchronized void doStop(){
isStopped = true;
this.interrupt(); //break pool thread out of dequeue() call.
}
public synchronized boolean isStopped(){
return isStopped;
}
}
The thread pool implementation consists of two parts. A
ThreadPool
class which is the public interface to the thread pool, and a PoolThread
class which implements the threads that execute the tasks.
To execute a task the method
ThreadPool.execute(Runnable r)
is called with a Runnable
implementation as parameter. The Runnable
is enqueued in the blocking queue internally, waiting to be dequeued.
The
Runnable
will be dequeued by an idle PoolThread
and executed. You can see this in the PoolThread.run()
method. After execution the PoolThread
loops and tries to dequeue a task again, until stopped.
To stop the
ThreadPool
the method ThreadPool.stop()
is called. The stop called is noted internally in the isStopped
member. Then each thread in the pool is stopped by calling doStop()
on each thread. Notice how the execute()
method will throw an IllegalStateException
if execute()
is called after stop()
has been called.
The threads will stop after finishing any task they are currently executing. Notice the
this.interrupt()
call in PoolThread.doStop()
. This makes sure that a thread blocked in a wait()
call inside the taskQueue.dequeue()
call breaks out of the wait()
call, and leaves the dequeue()
method call with an InterruptedException
thrown. This exception is caught in the PoolThread.run()
method, reported, and then the isStopped
variable is checked. Since isStopped
is now true, the PoolThread.run()
will exit and the thread dies.
--------------------------------------------------------------------------------------------------------
Reentrant Lock
------------------------------------------------------------------------------------------------------------
ThreadPoolExecutor
public class MyRunnable implements Runnable{
private String name;
public MyRunnable(String threadName){
this.name = threadName;
}
public void run(){
System.out.println("Start Thread : "+ name);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Ended Thread : "+ name);
}
}
--------------------------------------------------------
package com.Thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MyRunnableDemoExecutorService {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(5);
for(int i=0; i<10; i++){
Runnable runnable = new MyRunnable("MyWorkerThread :" + i);
executorService.execute(runnable);
}
executorService.shutdown();
while(!executorService.isTerminated()){}
System.out.println("All Service completed");
}
}
------------------------------------------------------------------------------------
OUTPUT:-
Start Thread : MyWorkerThread :0
Start Thread : MyWorkerThread :3
Start Thread : MyWorkerThread :2
Start Thread : MyWorkerThread :1
Start Thread : MyWorkerThread :4
Ended Thread : MyWorkerThread :2
Start Thread : MyWorkerThread :5
Ended Thread : MyWorkerThread :1
Start Thread : MyWorkerThread :6
Ended Thread : MyWorkerThread :0
Start Thread : MyWorkerThread :7
Ended Thread : MyWorkerThread :3
Start Thread : MyWorkerThread :8
Ended Thread : MyWorkerThread :4
Start Thread : MyWorkerThread :9
Ended Thread : MyWorkerThread :7
Ended Thread : MyWorkerThread :5
Ended Thread : MyWorkerThread :8
Ended Thread : MyWorkerThread :6
Ended Thread : MyWorkerThread :9
All Service completed
-----------------------------------------------------------------------------------------------------
ThreadPoolExecutor – Java Thread Pool Example
newFixedThreadPool
newScheduledThreadPool
newSingleThreadExecutor
newSingleThreadScheduledExecutor
ExecutorService executorService_2 = Executors.newCachedThreadPool(threadFactory);
ExecutorService executorService_3 = Executors.newFixedThreadPool(1);
ExecutorService executorService_4 = Executors.newFixedThreadPool(1, threadFactory);
ExecutorService executorService_5 = Executors.newSingleThreadExecutor();
ExecutorService executorService_6 = Executors.newSingleThreadExecutor(threadFactory);
ExecutorService executorService_7 = Executors.newWorkStealingPool();
ExecutorService executorService_8 = Executors.newWorkStealingPool(0);
ExecutorService executorService_9 = Executors.newScheduledThreadPool(0);
ExecutorService executorService_10 = Executors.newScheduledThreadPool(0, threadFactory);
ExecutorService executorService_11 = Executors.newSingleThreadScheduledExecutor();
ExecutorService executorService_12 = Executors.newSingleThreadScheduledExecutor(threadFactory);
ThreadPoolExecutor
to create thread pool in java.Java thread pool manages the collection of Runnable threads and worker threads execute Runnable from the queue. java.util.concurrent.Executors provide implementation of java.util.concurrent.Executor interface to create the thread pool in java. Let’s write a simple program to explain it’s working.
package com.journaldev.threadpool;
public class WorkerThread implements Runnable {
private String command;
public WorkerThread(String s){
this.command=s;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" Start. Command = "+command);
processCommand();
System.out.println(Thread.currentThread().getName()+" End.");
}
private void processCommand() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public String toString(){
return this.command;
}
}
ExecutorService Example
Here is the test program classSimpleThreadPool.java
, where we are creating fixed thread pool from Executors framework.package com.journaldev.threadpool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SimpleThreadPool {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
Runnable worker = new WorkerThread("" + i);
executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {
}
System.out.println("Finished all threads");
}
}
In above program, we are creating fixed size thread pool of 5 worker threads. Then we are submitting 10 jobs to this pool, since the pool size is 5, it will start working on 5 jobs and other jobs will be in wait state, as soon as one of the job is finished, another job from the wait queue will be picked up by worker thread and get's executed.Here is the output of the above program.
pool-1-thread-2 Start. Command = 1
pool-1-thread-4 Start. Command = 3
pool-1-thread-1 Start. Command = 0
pool-1-thread-3 Start. Command = 2
pool-1-thread-5 Start. Command = 4
pool-1-thread-4 End.
pool-1-thread-5 End.
pool-1-thread-1 End.
pool-1-thread-3 End.
pool-1-thread-3 Start. Command = 8
pool-1-thread-2 End.
pool-1-thread-2 Start. Command = 9
pool-1-thread-1 Start. Command = 7
pool-1-thread-5 Start. Command = 6
pool-1-thread-4 Start. Command = 5
pool-1-thread-2 End.
pool-1-thread-4 End.
pool-1-thread-3 End.
pool-1-thread-5 End.
pool-1-thread-1 End.
Finished all threads
The output confirms that there are five threads in the pool named from "pool-1-thread-1" to "pool-1-thread-5" and they are responsible to execute the submitted tasks to the pool.ThreadPoolExecutor Example
Executors class provide simple implementation of ExecutorService using ThreadPoolExecutor but ThreadPoolExecutor provides much more feature than that. We can specify the number of threads that will be alive when we create ThreadPoolExecutor instance and we can limit the size of thread pool and create our own RejectedExecutionHandler implementation to handle the jobs that can't fit in the worker queue.Here is our custom implementation of RejectedExecutionHandler interface.
package com.journaldev.threadpool;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
public class RejectedExecutionHandlerImpl implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println(r.toString() + " is rejected");
}
}
ThreadPoolExecutor
provides several methods using which we can find out the current state of executor, pool size, active thread count and task count. So I have a monitor thread that will print the executor information at certain time interval.package com.journaldev.threadpool;
import java.util.concurrent.ThreadPoolExecutor;
public class MyMonitorThread implements Runnable
{
private ThreadPoolExecutor executor;
private int seconds;
private boolean run=true;
public MyMonitorThread(ThreadPoolExecutor executor, int delay)
{
this.executor = executor;
this.seconds=delay;
}
public void shutdown(){
this.run=false;
}
@Override
public void run()
{
while(run){
System.out.println(
String.format("[monitor] [%d/%d] Active: %d, Completed: %d, Task: %d, isShutdown: %s, isTerminated: %s",
this.executor.getPoolSize(),
this.executor.getCorePoolSize(),
this.executor.getActiveCount(),
this.executor.getCompletedTaskCount(),
this.executor.getTaskCount(),
this.executor.isShutdown(),
this.executor.isTerminated()));
try {
Thread.sleep(seconds*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Here is the thread pool implementation example using ThreadPoolExecutor.package com.journaldev.threadpool;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class WorkerPool {
public static void main(String args[]) throws InterruptedException{
//RejectedExecutionHandler implementation
RejectedExecutionHandlerImpl rejectionHandler = new RejectedExecutionHandlerImpl();
//Get the ThreadFactory implementation to use
ThreadFactory threadFactory = Executors.defaultThreadFactory();
//creating the ThreadPoolExecutor
ThreadPoolExecutor executorPool = new ThreadPoolExecutor(2, 4, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2), threadFactory, rejectionHandler);
//start the monitoring thread
MyMonitorThread monitor = new MyMonitorThread(executorPool, 3);
Thread monitorThread = new Thread(monitor);
monitorThread.start();
//submit work to the thread pool
for(int i=0; i<10; i++){
executorPool.execute(new WorkerThread("cmd"+i));
}
Thread.sleep(30000);
//shut down the pool
executorPool.shutdown();
//shut down the monitor thread
Thread.sleep(5000);
monitor.shutdown();
}
}
Notice that while initializing the ThreadPoolExecutor, we are keeping initial pool size as 2, maximum pool size to 4 and work queue size as 2. So if there are 4 running tasks and more tasks are submitted, the work queue will hold only 2 of them and rest of them will be handled by RejectedExecutionHandlerImpl
.Here is the output of above program that confirms above statement.
pool-1-thread-1 Start. Command = cmd0
pool-1-thread-4 Start. Command = cmd5
cmd6 is rejected
pool-1-thread-3 Start. Command = cmd4
pool-1-thread-2 Start. Command = cmd1
cmd7 is rejected
cmd8 is rejected
cmd9 is rejected
[monitor] [0/2] Active: 4, Completed: 0, Task: 6, isShutdown: false, isTerminated: false
[monitor] [4/2] Active: 4, Completed: 0, Task: 6, isShutdown: false, isTerminated: false
pool-1-thread-4 End.
pool-1-thread-1 End.
pool-1-thread-2 End.
pool-1-thread-3 End.
pool-1-thread-1 Start. Command = cmd3
pool-1-thread-4 Start. Command = cmd2
[monitor] [4/2] Active: 2, Completed: 4, Task: 6, isShutdown: false, isTerminated: false
[monitor] [4/2] Active: 2, Completed: 4, Task: 6, isShutdown: false, isTerminated: false
pool-1-thread-1 End.
pool-1-thread-4 End.
[monitor] [4/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false
[monitor] [2/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false
[monitor] [2/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false
[monitor] [2/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false
[monitor] [2/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false
[monitor] [2/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false
[monitor] [0/2] Active: 0, Completed: 6, Task: 6, isShutdown: true, isTerminated: true
[monitor] [0/2] Active: 0, Completed: 6, Task: 6, isShutdown: true, isTerminated: true
Notice the change in active, completed and total completed task count of the executor. We can invoke shutdown() method to finish execution of all the submitted tasks and terminate the thread pool.If you want to schedule a task to run with delay or periodically then you can use ScheduledThreadPoolExecutor class. Read more about them at Java Schedule Thread Pool Executor.
--------------------------------------------------------------------------------------------------------------
The
java.util.concurrent.ThreadPoolExecutor
is an implementation of the ExecutorService
interface. The ThreadPoolExecutor
executes the given task (Callable
or Runnable
) using one of its internally pooled threads.
The thread pool contained inside the
ThreadPoolExecutor
can contain a varying amount of threads. The number of threads in the pool is determined by these variables:corePoolSize
maximumPoolSize
If less than
corePoolSize
threads are created in the the thread pool when a task is delegated to the thread pool, then a new thread is created, even if idle threads exist in the pool.
If the internal queue of tasks is full, and
corePoolSize
threads or more are running, but less than maximumPoolSize
threads are running, then a new thread is created to execute the task.
Here is a diagram illustrating the
ThreadPoolExecutor
principles:A ThreadPoolExecutor |
Creating a ThreadPoolExecutor
The
ThreadPoolExecutor
has several constructors available. For instance:int corePoolSize = 5;
int maxPoolSize = 10;
long keepAliveTime = 5000;
ExecutorService threadPoolExecutor =
new ThreadPoolExecutor(
corePoolSize,
maxPoolSize,
keepAliveTime,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()
);
However, unless you need to specify all these parameters explicitly for your
ThreadPoolExecutor
, it is often easier to use one of the factory methods in the java.util.concurrent.Executors
class, as shown in the ExecutorService text.
Next: ScheduledExecutorService
Example :-
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MyRunnableDemoExecutorService_2 {
public static void main(String[] args) {
int i =0;
ExecutorService executorService = Executors.newFixedThreadPool(5);
for( i =0; i<10; i++){
Runnable runnable = new Runnable(){
@Override
public void run() {
System.out.println("Started Thread :" + Thread.currentThread().getName() );
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Ended Thread :" + Thread.currentThread().getName());
}
};
executorService.execute(runnable);
}
executorService.shutdown();
while(!executorService.isTerminated()){}
System.out.println("Task Completed");
}
}
OUTPUT:-
Started Thread :pool-1-thread-4
Started Thread :pool-1-thread-5
Started Thread :pool-1-thread-3
Started Thread :pool-1-thread-2
Started Thread :pool-1-thread-1
Ended Thread :pool-1-thread-4
Started Thread :pool-1-thread-4
Ended Thread :pool-1-thread-5
Started Thread :pool-1-thread-5
Ended Thread :pool-1-thread-1
Started Thread :pool-1-thread-1
Ended Thread :pool-1-thread-3
Started Thread :pool-1-thread-3
Ended Thread :pool-1-thread-2
Started Thread :pool-1-thread-2
Ended Thread :pool-1-thread-4
Ended Thread :pool-1-thread-3
Ended Thread :pool-1-thread-2
Ended Thread :pool-1-thread-5
Ended Thread :pool-1-thread-1
Task Completed
----------------------------------------------------------------------------------------------------------------
ExecutorService
The
java.util.concurrent.ExecutorService
interface represents an asynchronous execution mechanism which is capable of executing tasks in the background. An ExecutorService
is thus very similar to a thread pool. In fact, the implementation of ExecutorService
present in the java.util.concurrent
package is a thread pool implementation.ExecutorService Example
Here is a simple Java
ExectorService
example:ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(new Runnable() {
public void run() {
System.out.println("Asynchronous task");
}
});
executorService.shutdown();
First an
ExecutorService
is created using the newFixedThreadPool()
factory method. This creates a thread pool with 10 threads executing tasks.
Second, an anonymous implementation of the
Runnable
interface is passed to the execute()
method. This causes the Runnable
to be executed by one of the threads in the ExecutorService
.Task Delegation
Here is a diagram illustrating a thread delegating a task to an
ExecutorService
for asynchronous execution:A thread delegating a task to an ExecutorService for asynchronous execution. |
Once the thread has delegated the task to the
ExecutorService
, the thread continues its own execution independent of the execution of that task.ExecutorService Implementations
Since
ExecutorService
is an interface, you need to its implementations in order to make any use of it. The ExecutorService
has the following implementation in the java.util.concurrent
package:Creating an ExecutorService
How you create an
ExecutorService
depends on the implementation you use. However, you can use the Executors
factory class to create ExecutorService
instances too. Here are a few examples of creating an ExecutorService
:ExecutorService executorService1 = Executors.newSingleThreadExecutor();
ExecutorService executorService2 = Executors.newFixedThreadPool(10);
ExecutorService executorService3 = Executors.newScheduledThreadPool(10);
ExecutorService Usage
There are a few different ways to delegate tasks for execution to an
ExecutorService
:- execute(Runnable)
- submit(Runnable)
- submit(Callable)
- invokeAny(...)
- invokeAll(...)
I will take a look at each of these methods in the following sections.
execute(Runnable)
The
execute(Runnable)
method takes a java.lang.Runnable
object, and executes it asynchronously. Here is an example of executing a Runnable
with an ExecutorService
:ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(new Runnable() {
public void run() {
System.out.println("Asynchronous task");
}
});
executorService.shutdown();
There is no way of obtaining the result of the executed
Runnable
, if necessary. You will have to use a Callable
for that (explained in the following sections).submit(Runnable)
The
submit(Runnable)
method also takes a Runnable
implementation, but returns a Future
object. This Future
object can be used to check if the Runnable
as finished executing.
Here is a
ExecutorService
submit()
example:Future future = executorService.submit(new Runnable() {
public void run() {
System.out.println("Asynchronous task");
}
});
future.get(); //returns null if the task has finished correctly.
submit(Callable)
The
submit(Callable)
method is similar to the submit(Runnable)
method except for the type of parameter it takes. The Callable
instance is very similar to a Runnable
except that its call()
method can return a result. The Runnable.run()
method cannot return a result.
The
Callable
's result can be obtained via the Future
object returned by the submit(Callable)
method. Here is an ExecutorService
Callable
example:Future future = executorService.submit(new Callable(){
public Object call() throws Exception {
System.out.println("Asynchronous Callable");
return "Callable Result";
}
});
System.out.println("future.get() = " + future.get());
The above code example will output this:
Asynchronous Callable
future.get() = Callable Result
invokeAny()
The
invokeAny()
method takes a collection of Callable
objects, or subinterfaces of Callable
. Invoking this method does not return a Future
, but returns the result of one of the Callable
objects. You have no guarantee about which of the Callable
's results you get. Just one of the ones that finish.
If one of the tasks complete (or throws an exception), the rest of the
Callable
's are cancelled.
Here is a code example:
ExecutorService executorService = Executors.newSingleThreadExecutor();
Set<Callable<String>> callables = new HashSet<Callable<String>>();
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 1";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 2";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 3";
}
});
String result = executorService.invokeAny(callables);
System.out.println("result = " + result);
executorService.shutdown();
This code example will print out the object returned by one of the
Callable
's in the given collection. I have tried running it a few times, and the result changes. Sometimes it is "Task 1", sometimes "Task 2" etc.invokeAll()
The
invokeAll()
method invokes all of the Callable
objects you pass to it in the collection passed as parameter. The invokeAll()
returns a list of Future
objects via which you can obtain the results of the executions of each Callable
.
Keep in mind that a task might finish due to an exception, so it may not have "succeeded". There is no way on a
Future
to tell the difference.
Here is a code example:
ExecutorService executorService = Executors.newSingleThreadExecutor();
Set<Callable<String>> callables = new HashSet<Callable<String>>();
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 1";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 2";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 3";
}
});
List<Future<String>> futures = executorService.invokeAll(callables);
for(Future<String> future : futures){
System.out.println("future.get = " + future.get());
}
executorService.shutdown();
ExecutorService Shutdown
When you are done using the
ExecutorService
you should shut it down, so the threads do not keep running.
For instance, if your application is started via a
main()
method and your main thread exits your application, the application will keep running if you have an active ExexutorService
in your application. The active threads inside this ExecutorService
prevents the JVM from shutting down.
To terminate the threads inside the
ExecutorService
you call its shutdown()
method. The ExecutorService
will not shut down immediately, but it will no longer accept new tasks, and once all threads have finished current tasks, the ExecutorService
shuts down. All tasks submitted to the ExecutorService
before shutdown()
is called, are executed.
If you want to shut down the
ExecutorService
immediately, you can call the shutdownNow()
method. This will attempt to stop all executing tasks right away, and skips all submitted but non-processed tasks. There are no guarantees given about the executing tasks. Perhaps they stop, perhaps the execute until the end. It is a best effort attempt.
Next: ThreadPoolExecutor
2. Java ExecutorService - Part 2 - Type of Pools
4.Java ExecutorService - Part 4 - Callable / Future
Java Thread Pool Executor Example
Usually, when you develop a simple, concurrent-programming application in Java, you create some
Runnable
objects and then create the corresponding Thread
objects to execute them. Since Java 5, the Java concurrency API provides a mechanism Executor framework. This is around the Executor
interface, its sub-interface ExecutorService
, and the ThreadPoolExecutor
class that implements both interfaces. This mechanism separates the task creation and its execution. With an executor, you only have to implement the Runnable
objects and send them to the executor. It is responsible for their execution, instantiation, and running with necessary threads. But it goes beyond that and improves performance using a pool of threads. When you send a task to the executor, it tries to use a pooled thread for the execution of this task, to avoid continuous spawning of threads.
In this tutorial, we will look at a very basic example of thread pool executor. In coming posts, we will learn about more complex tasks.
1) Create a task to execute
Obviously, first step is to have a task which you would like to execute using
Executors
.class Task implements Runnable { private String name; public Task(String name) { this .name = name; } public String getName() { return name; } @Override public void run() { try { Long duration = ( long ) (Math.random() * 10 ); System.out.println( "Doing a task during : " + name); TimeUnit.SECONDS.sleep(duration); } catch (InterruptedException e) { e.printStackTrace(); } } } |
2) Execute tasks using Executors
Now all you have to do is to create an instance of
ThreadPoolExecutor
and pass the tasks to be executed into it’s execute()
method.package com.howtodoinjava.demo.multithreading; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class BasicThreadPoolExecutorExample { public static void main(String[] args) { //Use the executor created by the newCachedThreadPool() method //only when you have a reasonable number of threads //or when they have a short duration. ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool(); for ( int i = 0 ; i <= 5 ; i++) { Task task = new Task( "Task " + i); System.out.println( "A new task has been added : " + task.getName()); executor.execute(task); } executor.shutdown(); } } Output: A new task has been added : Task 0 A new task has been added : Task 1 A new task has been added : Task 2 A new task has been added : Task 3 A new task has been added : Task 4 A new task has been added : Task 5 Doing a task during : Task 5 Doing a task during : Task 0 Doing a task during : Task 2 Doing a task during : Task 1 Doing a task during : Task 4 Doing a task during : Task 3 |
Important Points:
- The
ThreadPoolExecutor
class has four different constructors but, due to their complexity, the Java concurrency API provides theExecutors
class to construct executors and other related objects. Although we can createThreadPoolExecutor
directly using one of its constructors, it’s recommended to use theExecutors
class. - The cached thread pool, we have created above, creates new threads if needed to execute the new tasks, and reuses the existing ones if they have finished the execution of the task they were running, which are now available. The cached thread pool has, however, a disadvantage of constant lying threads for new tasks, so if you send too many tasks to this executor, you can overload the system. This can be overcome using fixed thread pool, which we will learn in next tutorial.
- One critical aspect of the
ThreadPoolExecutor
class, and of the executors in general, is that you have to end it explicitly. If you don’t do this, the executor will continue its execution and the program won’t end. If the executor doesn’t have tasks to execute, it continues waiting for new tasks and it doesn’t end its execution. A Java application won’t end until all its non-daemon threads finish their execution, so, if you don’t terminate the executor, your application will never end. - To indicate to the executor that you want to finish it, you can use the
shutdown()
method of theThreadPoolExecutor
class. When the executor finishes the execution of all pending tasks, it finishes its execution. After you call theshutdown()
method, if you try to send another task to the executor, it will be rejected and the executor will throw aRejectedExecutionException
exception. - The
ThreadPoolExecutor
class provides a lot of methods to obtain information about its status. We used in the example thegetPoolSize()
,getActiveCount()
, andgetCompletedTaskCount()
methods to obtain information about the size of the pool, the number of threads, and the number of completed tasks of the executor. You can also use thegetLargestPoolSize()
method that returns the maximum number of threads that has been in the pool at a time. - The
ThreadPoolExecutor
class also provides other methods related with the finalization of the executor. These methods are:- shutdownNow(): This method shut downs the executor immediately. It doesn’t execute the pending tasks. It returns a list with all these pending tasks. The tasks that are running when you call this method continue with their execution, but the method doesn’t wait for their finalization.
- isTerminated(): This method returns true if you have called the
shutdown()
orshutdownNow()
methods and the executor finishes the process of shutting it down. - isShutdown(): This method returns true if you have called the
shutdown()
method of the executor. - awaitTermination(longtimeout,TimeUnitunit): This method blocks the calling thread until the tasks of the executor have ended or the timeout occurs. The
TimeUnit
class is an enumeration with the following constants:DAYS
,HOURS
,MICROSECONDS
etc.
----------------------------------------------------------------------------------------------------------------
ScheduledExecutorService
Jakob Jenkov
Last update: 2014-06-23 |
The
java.util.concurrent.ScheduledExecutorService
is an ExecutorService
which can schedule tasks to run after a delay, or to execute repeatedly with a fixed interval of time in between each execution. Tasks are executed asynchronously by a worker thread, and not by the thread handing the task to the ScheduledExecutorService
.ScheduledExecutorService Example
Here is a simple
ScheduledExecutorService
example:ScheduledExecutorService scheduledExecutorService =
Executors.newScheduledThreadPool(5);
ScheduledFuture scheduledFuture =
scheduledExecutorService.schedule(new Callable() {
public Object call() throws Exception {
System.out.println("Executed!");
return "Called!";
}
},
5,
TimeUnit.SECONDS);
First a
ScheduledExecutorService
is created with 5 threads in. Then an anonymous implementation of the Callable
interface is created and passed to the schedule()
method. The two last parameters specify that the Callable
should be executed after 5 seconds.ScheduledExecutorService Implementations
Since
ScheduledExecutorService
is an interface, you will have to use its implementation in the java.util.concurrent
package, in order to use it. ScheduledExecutorService
as the following implementation:- ScheduledThreadPoolExecutor
Creating a ScheduledExecutorService
How you create an
ScheduledExecutorService
depends on the implementation you use. However, you can use the Executors
factory class to create ScheduledExecutorService
instances too. Here is an example:ScheduledExecutorService scheduledExecutorService =
Executors.newScheduledThreadPool(5);
ScheduledExecutorService Usage
Once you have created a
ScheduledExecutorService
you use it by calling one of its methods:- schedule (Callable task, long delay, TimeUnit timeunit)
- schedule (Runnable task, long delay, TimeUnit timeunit)
- scheduleAtFixedRate (Runnable, long initialDelay, long period, TimeUnit timeunit)
- scheduleWithFixedDelay (Runnable, long initialDelay, long period, TimeUnit timeunit)
I will briefly cover each of these methods below.
schedule (Callable task, long delay, TimeUnit timeunit)
This method schedules the given
Callable
for execution after the given delay.
The method returns a
ScheduledFuture
which you can use to either cancel the task before it has started executing, or obtain the result once it is executed.
Here is an example:
ScheduledExecutorService scheduledExecutorService =
Executors.newScheduledThreadPool(5);
ScheduledFuture scheduledFuture =
scheduledExecutorService.schedule(new Callable() {
public Object call() throws Exception {
System.out.println("Executed!");
return "Called!";
}
},
5,
TimeUnit.SECONDS);
System.out.println("result = " + scheduledFuture.get());
scheduledExecutorService.shutdown();
This example outputs:
Executed!
result = Called!
schedule (Runnable task, long delay, TimeUnit timeunit)
This method works like the method version taking a
Callable
as parameter, except a Runnable
cannot return a value, so the ScheduledFuture.get()
method returns null when the task is finished.scheduleAtFixedRate (Runnable, long initialDelay, long period, TimeUnit timeunit)
This method schedules a task to be executed periodically. The task is executed the first time after the
initialDelay
, and then recurringly every time the period
expires.
If any execution of the given task throws an exception, the task is no longer executed. If no exceptions are thrown, the task will continue to be executed until the
ScheduledExecutorService
is shut down.
If a task takes longer to execute than the period between its scheduled executions, the next execution will start after the current execution finishes. The scheduled task will not be executed by more than one thread at a time.
scheduleWithFixedDelay (Runnable, long initialDelay, long period, TimeUnit timeunit)
This method works very much like
scheduleAtFixedRate()
except that the period
is interpreted differently.
In the
scheduleAtFixedRate()
method the period
is interpreted as a delay between the start of the previous execution, until the start of the next execution.
In this method, however, the
period
is interpreted as the delay between the end of the previous execution, until the start of the next. The delay is thus between finished executions, not between the beginning of executions.ScheduledExecutorService Shutdown
Just like an
ExecutorService
, the ScheduledExecutorService
needs to be shut down when you are finished using it. If not, it will keep the JVM running, even when all other threads have been shut down.
You shut down a
ScheduledExecutorService
using the shutdown()
or shutdownNow()
methods which are inherited from the ExecutorService
interface. See the ExecutorService Shutdown section for more information.
No comments:
Post a Comment