Sie sind auf Seite 1von 44

1 Threading tutorial: Multi-threading in Java

Overview

Threads are simply subprograms those can be executed


simultaneously with shared memory space. A java process can contain
multiple threads. Each java process has at least one thread, the main
thread. Multi-threading in Java is an important and interesting topic
to learn.

Multi-threading in Java

Now lets discuss the ways to create individual threads in a Java


program.

Creating a thread in Java

Threads can be created in two ways:

1.Extending Thread class

This is done by extending the Thread class in Java and overriding the
run method. In the run method we can specify the logic to perform in
the new thread. Let us discuss with an example.

The class ThreadSample.java given here is extending the Thread class.


In the run method we are just printing the multiples of 5 from 0 to 50
along with the thread name, with an interval of 1 second.

public class ThreadSample extends Thread {

int count = 0;
public ThreadSample() {}

public void run() {


while (count < 50) { try { count = count + 5;
System.out.println("Current thread : " +
Thread.currentThread().getName() + " " + "count =" + count);
sleep(1000); } catch (InterruptedException ie) { ie.printStackTrace();
} } } }

Now let us see the main class to test the code.The main method just
starts the new thread from the main thread. So there will be two
threads the main thread and the child thread.

The main thread will wait till the child thread finishes. Remember, we
have put our thread logic in run method, but we are not directly
invoking the run method by threadSample.run(), instead we are calling
threadsample.start().

To start a thread the start method needs to be called. If we call the


run() method directly the method will be executed from the calling
thread, but separate thread will not be created for that task.

So for creating new thread the start() method should be used. It is


better if you give a name while initializing a thread object. Please
check the java doc for Thread class to know about the various
constructors.

public class ThreadMain {

public ThreadMain() {}

public static void main(String[] args) {


ThreadSample threadSample = new ThreadSample();
System.out.println("Current thread : Thread name :" +
Thread.currentThread().getName());
threadSample.start();

}
}

Now let us see the output.From the output we can clearly understand
the concept of threading by extending Thread class.
Output

Current thread: Thread name: main

Current thread : Thread-0 count =5

Current thread : Thread-0 count =10

Current thread : Thread-0 count =15

Current thread : Thread-0 count =20

Current thread : Thread-0 count =25

Current thread : Thread-0 count =30

Current thread : Thread-0 count =35

Current thread : Thread-0 count =40

Current thread : Thread-0 count =45

Current thread : Thread-0 count =50

2.Using Runnable interface

A thread can be created by implementing the Runnable interface. This


interface is having a run() method. In the method we can put the logic
to be performed in the thread.

We know multiple overloading is not allowed in Java by extending


multiple classes together. While creating a thread, if we are
extending the Thread class, we would not be able to to extend more
classes.

So if that class needs to be a business class, extending Thread class


would not be a better option to create a Thread. In that case, it is
preferable to use the Runnable interface.The example explained earlier
in this section is redesigned by implementing the Runnable interface.

public class RunnableSample implements Runnable {

int count = 0;
public RunnableSample() {}
public void run() {
while (count < 50) { try { count = count + 5;
System.out.println("Current thread : " +
Thread.currentThread().getName() + " " + "count =" + count);
Thread.sleep(1000); } catch (InterruptedException ie) {
ie.printStackTrace(); } } } }

Now let us see the main class to start the thread. First we need to
create a Thread object using the runnable object created. Then we
need to call the start() method to start the new thread.

public class RunnableMain {

public RunnableMain() {}

public static void main(String[] args) {


RunnableSample runnableSample = new RunnableSample();
System.out.println("Current thread : Thread name :" +
Thread.currentThread().getName());
Thread runnableThread = new Thread(runnableSample);
runnableThread.start();
}
}

Now let us see the output.It will be exactly the same as that of the
previous example.

Output

Current thread: Thread name: main

Current thread : Thread-0 count =5

Current thread : Thread-0 count =10

Current thread : Thread-0 count =15

Current thread : Thread-0 count =20

Current thread : Thread-0 count =25

Current thread : Thread-0 count =30


Current thread : Thread-0 count =35

Current thread : Thread-0 count =40

Current thread : Thread-0 count =45

Current thread : Thread-0 count =50

Thread Life Cycle

A thread goes through various stages in its entire life time. The
stages are listed here.

1) New State: This is the state of a thread when it is created.

2) Runnable State: When the thread is ready to run.

3) Running State: When the thread is running

4) Blocked State: When the thread is sleeping or waiting.

5) Dead State: When the thread is finished.


2 Threading tutorial: Concurrency in Java

Concurrency is an issue facing in any multi-threaded environment. If


we are using multiple threads in a java process, then we need to
ensure thread safety for each objects.

In simple words, if multiple threads are accessing same piece of data


and trying to change the same at a time, it will be a problem.
Fortunately, Java provides a mechanism to overcome this issue. There
is a synchronized keyword in Java provides the solution for this
problem.

By using this technique, each thread gets lock on a particular


object and after getting the lock that thread is manipulating on that
object. By that time other threads trying to access the same object
needs to wait till the current thread releases the lock on that
object.

JVM is doing is the lock allocation mechanism. After the lock is


released from one thread, the lock will be allocated to the waiting
thread. If there are multiple threads waiting, then lock will be
allotted on basis of priority.

1)Synchronized non-static methods

Now let us see how synchronized key word is working. Let us discuss
with an example. Here we are defining a class NumericCounter.java. It
has a method countNumbers().

Here we specified it as synchronized, that means only one thread can


access the method of the current object at a time. If a
second thread is also trying to access the same method of the same
NumericCounter object, it needs to wait to get the lock on that
particular object.

If the second thread is trying to execute the method using another


NumericCounter object, then it will be executed. Once a thread
acquires lock on a particular object, no other threads can execute any
of the synchronized methods of that class on that object.
public class NumericCounter {

public NumericCounter() {}

public synchronized void countNumbers() {


System.out.println("Now this method is locked by thread
:"+Thread.currentThread().getName());
int count = 0;
while (count < 50) { try { System.out.println("Current thread : " +
Thread.currentThread().getName() + "; Count = " + count); count =
count + 5; Thread.sleep(1000); } catch (InterruptedException ie) {
ie.printStackTrace(); } } System.out.println("Lock is going to be
released for thread :"+Thread.currentThread().getName()); } }

Now let us see the main class to run the NumericCounter


class, SynchSample.java.

public class SynchSample implements Runnable {

private NumericCounter counter = null;


public SynchSample(NumericCounter counter) {
this.counter = counter;
}

public void run() {


counter.countNumbers();
}

public static void main(String[] args) {


NumericCounter counter = new NumericCounter();
//USANDO EL MISMO CONTADOR

SynchSample firstInstance = new SynchSample(counter);


SynchSample secondInstance = new SynchSample(counter);
Thread firstThread = new Thread(firstInstance, "firstThread");
Thread secondThread = new Thread(secondInstance, "secondThread");
firstThread.start();
secondThread.start();
}
}
It is implementing Runnble interface. In the run method we are calling
the countNumbers() method. Now two instances of SynchSample is
creating using the same NumericCounter object. Since the SynchSample
is implementing the Runnable interface, the SynchSample objects will
be Runnables too.

Now we can create two threads using two runnable instances. Two
threads are named as firstThread and secondThread. Now start both the
threads. As of our assumption one thread needs to get the lock on the
object.

After that thread is released from that lock, then the second thread
gets its lock on the object. So either 'firstThread' or 'secondThread'
acquires lock on NumericCounter object after releasing the lock the
second one will get the lock on the same.

Now let us verify the output. In my environment 'firstThread' attained


the lock first. Then 'secondThread' got the lock. The order may be
different in your case. In any case we can verify the locking
mechanism.

Output

Now this method is locked by thread: firstThread

Current thread : firstThread; Count = 0

Current thread : firstThread; Count = 5

Current thread : firstThread; Count = 10

Current thread : firstThread; Count = 15

Current thread : firstThread; Count = 20

Current thread : firstThread; Count = 25

Current thread : firstThread; Count = 30

Current thread : firstThread; Count = 35

Current thread : firstThread; Count = 40

Current thread : firstThread; Count = 45


Lock is going to be released for thread: firstThread

Now this method is locked by thread: secondThread

Current thread : secondThread; Count = 0

Current thread : secondThread; Count = 5

Current thread : secondThread; Count = 10

Current thread : secondThread; Count = 15

Current thread : secondThread; Count = 20

Current thread : secondThread; Count = 25

Current thread : secondThread; Count = 30

Current thread : secondThread; Count = 35

Current thread : secondThread; Count = 40

Current thread : secondThread; Count = 45

Lock is going to be released for thread: secondThread

Now let us see what happens if two threads calls the same method on
different objects. In this case the SynchSample class will be having
two NumericCounter objects. And two threads are creating, they are not
sharing the same NumericCounter object. They are having different
NumericCounter objects. Now two threads can execute
the countNumbers() in parallel.

public class SynchSample implements Runnable {

private NumericCounter counter = null;

public SynchSample(NumericCounter counter) {


this.counter = counter;
}

public void run() {


counter.countNumbers();
}
public static void main(String[] args) {
NumericCounter counterFirst = new NumericCounter();
NumericCounter counterSecond = new NumericCounter();
//USANDO DOS OBJETOS CONTADOR

SynchSample firstInstance = new SynchSample(counterFirst);


SynchSample secondInstance = new SynchSample(counterSecond);
Thread firstThread = new Thread(firstInstance, "firstThread");
Thread secondThread = new Thread(secondInstance, "secondThread");
firstThread.start();
secondThread.start();
}
}

Now let us verify the output. The output may be different in different
environments. But it can give a correct idea.

Output

Now this method is locked by thread: firstThread

Current thread : firstThread; Count = 0

Now this method is locked by thread :secondThread

Current thread : secondThread; Count = 0

Current thread : secondThread; Count = 5

Current thread : firstThread; Count = 5

Current thread : firstThread; Count = 10

Current thread : secondThread; Count = 10

Current thread : firstThread; Count = 15

Current thread : secondThread; Count = 15

Current thread : secondThread; Count = 20

Current thread : firstThread; Count = 20

Current thread : firstThread; Count = 25

Current thread : secondThread; Count = 25

Current thread : secondThread; Count = 30

Current thread : firstThread; Count = 30


Current thread : firstThread; Count = 35

Current thread : secondThread; Count = 35

Current thread : firstThread; Count = 40

Current thread : secondThread; Count = 40

Current thread : firstThread; Count = 45

Current thread : secondThread; Count = 45

Lock is going to be released for thread :firstThread

Lock is going to be released for thread :secondThread

2)Synchronized static methods

A non static synchronized method of a class can be executed by


multiple threads at a time on different objects. That the above
example showed us.

But if we specify a method as static and is synchronized then, in any


way only one thread can execute it at a time. It means the lock is not
on individual objects, but it is on the class object.

The above explained classes can be modified for verifying the result.

public class NumericCounter {

public NumericCounter() {}

public static synchronized void countNumbers() {


System.out.println("Now this method is locked by thread
:"+Thread.currentThread().getName());
int count = 0;
while (count < 50) { try { System.out.println("Current thread : " +
Thread.currentThread().getName() + "; Count = " + count); count =
count + 5; Thread.sleep(1000); } catch (InterruptedException ie) {
ie.printStackTrace(); } } System.out.println("Lock is going to be
released for thread :"+Thread.currentThread().getName()); } }
The main class is given below.

public class SynchSample implements Runnable {

private NumericCounter counter = null;

public SynchSample(NumericCounter counter) {


this.counter = counter;
}

public void run() {


counter.countNumbers();
}

public static void main(String[] args) {


NumericCounter counterFirst = new NumericCounter();
NumericCounter counterSecond = new NumericCounter();
SynchSample firstInstance = new SynchSample(counterFirst);
SynchSample secondInstance = new SynchSample(counterSecond);
Thread firstThread = new Thread(firstInstance, "firstThread");
Thread secondThread = new Thread(secondInstance, "secondThread");
firstThread.start();
secondThread.start();
}
}

Now let us verify the output.

Output

Now this method is locked by thread :firstThread

Current thread : firstThread; Count = 0

Current thread : firstThread; Count = 5

Current thread : firstThread; Count = 10

Current thread : firstThread; Count = 15

Current thread : firstThread; Count = 20


Current thread : firstThread; Count = 25

Current thread : firstThread; Count = 30

Current thread : firstThread; Count = 35

Current thread : firstThread; Count = 40

Current thread : firstThread; Count = 45

Lock is going to be released for thread :firstThread

Now this method is locked by thread :secondThread

Current thread : secondThread; Count = 0

Current thread : secondThread; Count = 5

Current thread : secondThread; Count = 10

Current thread : secondThread; Count = 15

Current thread : secondThread; Count = 20

Current thread : secondThread; Count = 25

Current thread : secondThread; Count = 30

Current thread : secondThread; Count = 35

Current thread : secondThread; Count = 40

Current thread : secondThread; Count = 45

Lock is going to be released for thread :secondThread

3)synchronized block

We can write a certain piece of code in a synchronized block. Like

synchronized(emp){

//some piece of code

where emp is an object. Here the code will be executed only when lock
on object emp is achieved by the calling thread. Let us verify the
result by an example where we can reuse the same code explained
earlier.
public class NumericCounter {

public NumericCounter() {}

public void countNumbers() {


synchronized (this){
System.out.println("Now this method is locked by thread
:"+Thread.currentThread().getName());
int count = 0;
while (count < 50) { try { System.out.println("Current thread : " +
Thread.currentThread().getName() + "; Count = " + count); count =
count + 5; Thread.sleep(1000); } catch (InterruptedException ie) {
ie.printStackTrace(); } } System.out.println("Lock is going to be
released for thread :"+Thread.currentThread().getName()); } } }

Here inside the countNumbers() method, we put a synchronized block,


that means to execute that block lock on the current NumericCounter
object. To verify the result two threads must use the same
NumericCounter object.

Now let us see the main class.

public class SynchSample implements Runnable {

private NumericCounter counter = null;

public SynchSample(NumericCounter counter) {


this.counter = counter;
}

public void run() {


counter.countNumbers();
}

public static void main(String[] args) {


NumericCounter counterFirst = new NumericCounter();
//USANDO EL MISMO CONTADOR
SynchSample firstInstance = new SynchSample(counterFirst);
SynchSample secondInstance = new SynchSample(counterFirst);
Thread firstThread = new Thread(firstInstance, "firstThread");
Thread secondThread = new Thread(secondInstance, "secondThread");
firstThread.start();
secondThread.start();
}
}

Output

Now this method is locked by thread :firstThread

Current thread : firstThread; Count = 0

Current thread : firstThread; Count = 5

Current thread : firstThread; Count = 10

Current thread : firstThread; Count = 15

Current thread : firstThread; Count = 20

Current thread : firstThread; Count = 25

Current thread : firstThread; Count = 30

Current thread : firstThread; Count = 35

Current thread : firstThread; Count = 40

Current thread : firstThread; Count = 45

Lock is going to be released for thread :firstThread

Now this method is locked by thread :secondThread

Current thread : secondThread; Count = 0

Current thread : secondThread; Count = 5

Current thread : secondThread; Count = 10

Current thread : secondThread; Count = 15

Current thread : secondThread; Count = 20

Current thread : secondThread; Count = 25

Current thread : secondThread; Count = 30

Current thread : secondThread; Count = 35


Current thread : secondThread; Count = 40

Current thread : secondThread; Count = 45

Lock is going to be released for thread :secondThread

Volatile keyword in Java

If we are specifying a variable as volatile then that variable is not


storing in the cache. Instead it is storing in the main memory. So if
multiple threads are using the variable all those threads are getting
the updated value of the variable.
3 Threading tutorial: Communication between threads in
Java

In a multithreaded Java process, it is often needed a communication


between different threads. This inter-thread communication is
performing using wait(), notify(), and notifyAll() methods of
Java.Lang.Object class. The idea is going to be clear once we do an
example which has two child threads and those two child threads are
communicating with each other.

Communication between threads in Java Example

Here we are discussing an example which has two threads. One thread is
printing even numbers from 0 to 50, while the other thread is printing
odd numbers from 0 to 50. Our aim is to print even and odd numbers
alternately.

The class EvenRunnable.java has the logic in the run() method, to


print the even numbers. Similarly the class OddRunnable has the logic
to print odd numbers. Let us see the code first.

public class EvenRunnable implements Runnable {

private int number = 2;


private Object shared = null;

public EvenRunnable(Object object) {


shared = object;
}

public void run() {


while (number < 50) { synchronized (shared) { System.out.println("Even
number = " + number); number = number + 2; try { Thread.sleep(500);
//only to view sequence of execution

shared.notify(); shared.wait(); } catch (InterruptedException e) {


e.printStackTrace(); } } } } }
public class OddRunnable implements Runnable {

int oddNumber = 1;
private Object shared = null;

public OddRunnable(Object object) {


shared = object;
}

public void run() {


while (oddNumber < 50) { synchronized (shared) {
System.out.println("Odd number = " + oddNumber); oddNumber = oddNumber
+ 2; try { Thread.sleep(500);

//only to view the sequence of execution

shared.notify(); shared.wait(); } catch (InterruptedException e) {


e.printStackTrace(); } } } } }

Now let us see the main class.

public class Main {

public Main(){}

public static void main(String[] args) {


Object shared = new Object();
EvenRunnable evenRunnable = new EvenRunnable(shared);
OddRunnable oddRunnable = new OddRunnable(shared);
Thread evenThread = new Thread(evenRunnable, "evenThread");
Thread oddThread = new Thread(oddRunnable, "oddThread");
oddThread.start();
evenThread.start();
}
}

Here we have a common object for these two threads. And only one
thread is allowed to access that object at a time. So synchronized
block should be there.
Our main method of Main.java creates two threads with names
'evenThread' and 'oddThread' from the Runnable objects. Then start()
method of the two threads are calling.

Assume 'oddThread' started first and it got the lock on shared object.
So 'evenThread' needs to wait to get the lock. Now 'oddThread' prints
the value and it sleeps for few moments.

Then the shared.notify() will be called after incrementing the odd


number by 2. Then calling wait() method on shared. It releases the
lock for 'oddThread' on shared and it is moving to waiting state.

Now 'evenThread' is holding the lock. It prints an even number, then


sleeping for a moment, then incrementing the number by two. When the
'evenThread' calls the notify() method the 'oddThread' wakes up and
when wait() is called for 'evenThread' then 'oddThread' is getting
lock back on shared. And it prints the next odd number. This process
continuous till the number reaches maximum value of 50. This can be
verified the output of our Main.java

Output

Odd number = 1
Even number = 2
Odd number = 3
Even number = 4
Odd number = 5
Even number = 6
Odd number = 7
Even number = 8
Odd number = 9
Even number = 10
Odd number = 11
Even number = 12
Odd number = 13
Even number = 14
Odd number = 15
Even number = 16
Odd number = 17
Even number = 18
Odd number = 19
Even number = 20
Odd number = 21
Even number = 22
Odd number = 23
Even number = 24
Odd number = 25
Even number = 26
Odd number = 27
Even number = 28
Odd number = 29
Even number = 30
Odd number = 31
Even number = 32
Odd number = 33
Even number = 34
Odd number = 35
Even number = 36
Odd number = 37
Even number = 38
Odd number = 39
Even number = 40
Odd number = 41
Even number = 42
Odd number = 43
Even number = 44
Odd number = 45
Even number = 46
Odd number = 47
Even number = 48
Odd number = 49

Summary

Inter-thread communication can be done by three methods of


Java.lang.Object class

1) wait() - It releases lock from the current thread and current


thread is moving to the waiting state.

2) notify() - It wakes up the first thread that is waiting to get


lock on a particular object. It is not releasing the lock.

3) notifyAll() - It wakes up all the threads those are waiting to get


lock on a particular object. It is not releasing the lock.

Remember these methods should be called only from a synchronized


context.
4 Threading tutorial: Thread priorities in Java

Thread Priorities in Java

If there are multiple threads in an application, then those threads


reaches to the ready to run state based on thread priority.

JVM contains a thread scheduler and it is managing the threads based


on priorities. Priority is represented by an integer value from 1 to
10.

A priority value of 1 means that thread is having the minimum priority


value. A priority value of 10 means it has the maximum priority value.
The default priority value is 5.

In program it is possible to change the priority value using


setPriority(int value) method of Thread class. Also there are
constants to specify the priority value:.Thread.MIN_PRIORITY,
Thread.MAX_PRIORITY, Thread.NORM_PRIORITY are integer values 1 , 5 and
10.

But it is not preferable to develop multi-threaded applications by


trusting the priority values. The behavior is different in different
platforms and in different JVMs.
5 Threading tutorial: The join method in Java

Thread class is having a join() method. Assume from thread Thread1


we are calling Thread2.join(). In this case the calling thread
(Thread1) is waiting to get the Thread2 to get completed and there
after Thread1 resumes its execution.

If we specify Thread2.join(long interval) then the parameter


interval is the maximum time by which the Thread1 can stay as
blocked (Before coming back to runnable). The idea of join() will
become clear once we discuss an example.

The join method in threading Example

We have two threads. First thread is printing multiples of 10 from 0


to 100 and second thread is printing multiples of 10 from 100 to 200.
We need to join second thread behind first thread so that multiples of
10 from 0 to 200 are printing. Now let us see the first thread.

public class FirstThread extends Thread {

int number = 0;
public FirstThread(String name) {
super(name);
}

public void run() {


while (number < 100) { System.out.println("Number in " +
Thread.currentThread().getName() + " is " + number); try {
sleep(1000); number = number + 10; } catch (InterruptedException e) {
e.printStackTrace(); } } } }

Now let us see the second thread. It contains a reference to the first
thread. In the run method we are calling the join method. So it is not
going to print any number till the end of execution of first thread.
After the end of execution of first thread is over, second thread is
starting to print its numbers.
public class SecondThread extends Thread {

int number = 100;


Thread firstThread = null;

public SecondThread(String name, Thread first) {


super(name);
firstThread = first;
}

public void run() {


try {
firstThread.join();
System.out.println("Joining second thread now");
while (number <= 200) { System.out.println("Number in " +
Thread.currentThread().getName() + " = " + number); sleep(1000);
number = number + 10; } } catch (InterruptedException e) {
e.printStackTrace(); } } }

Now let us see the main class. It simply creates objects of the above
classes. Second thread is having a reference to the first thread so
that it can call the join() on it. Remember, if we are using this
method, we should handle the InterruptedException too.

public class Main {

public Main(){}

public static void main(String[]args){


FirstThread firstThread = new FirstThread("firstThread");
SecondThread secondThread = new
SecondThread("secondThread",firstThread);
firstThread.start();
secondThread.start();
}}

Now let us verify the output.The output clearly shows us how join()
works. Multiples of 10 from 0 to 100 is displaying first and then from
100 to 200. Thread name also displayed, so it is very clear now.
Output

Number in firstThread = 0

Number in firstThread = 10

Number in firstThread = 20

Number in firstThread = 30

Number in firstThread = 40

Number in firstThread = 50

Number in firstThread = 60

Number in firstThread = 70

Number in firstThread = 80

Number in firstThread = 90

Joining second thread now

Number in secondThread = 100

Number in secondThread = 110

Number in secondThread = 120

Number in secondThread = 130

Number in secondThread = 140

Number in secondThread = 150

Number in secondThread = 160

Number in secondThread = 170

Number in secondThread = 180

Number in secondThread = 190

Number in secondThread = 200


5 Threading tutorial: The yield method in Java

The yield() is a static method in Thread class. It changes state of a


running thread to runnable state. This method can be applied to only
those threads having the same priority.

Now, if there is a thread of same priority waiting to get a chance to


start running, it will move to running state (the thread scheduler is
managing it).

But practically, we cannot assure the proper working of yield()


method, since its implementation is different in different platforms
and different JVMs.
6 Threading tutorial: The sleep method in Java

The Thread class is having a method call sleep(long interval). It


makes to sleep the current thread for the specified interval.

The interval specified will be minimum time it stays in the sleeping


state. We cannot guarantee, when it is returning to running.

This method is throwing InterruptedException. So in code we need to


handle that also.

The sleep method in threading Example

Let us see an example. Here we are trying to display numbers from 1 to


10 with an interval of 5 seconds. After printing each number, thread
stays in sleeping mode for 5000 ms.

public class SleepSample extends Thread {

public SleepSample() {}

public void run() {


int number = 0;
while (number < 10) { System.out.println("Number = " + number); try {
number++; sleep(5000); } catch (InterruptedException e) {
e.printStackTrace(); } } }

public static void main(String[] args) {

SleepSample sample = new SleepSample();

sample.start(); }

The program just prints the numbers with good interval. It is enough
to understand the concept.
7 Threading tutorial: Daaemon thread in Java

In addition to the working threads, background threads are needed for


doing background tasks. The concept Daemon thread in Java is intended
for this purpose.

Daemon thread in Java

Daemon threads are supporting threads those are running at the back
ground. These threads are usually intended to give support to other
threads.

The best example of daemon thread is the garbage collector. A thread


can be changed to daemon by using the setDaemon(boolean arg) method of
Thread class.

To make a thread as daemon, setdaemon(true) needs to be called. A


thread can be converted to daemon before it starts. In other words,
once the start() method is called, we should not use setDaemon()
method on that thread.

A java process terminates when its main thread is over. Main


thread leaves its execution when all the child threads are over. So
the main thread waits for all its child threads to complete.

Once child threads are over main thread also exits. But it is not
waiting for daemon threads. If there are only daemon threads then main
thread is not waiting for them to get complete.

An application gets terminated so the main thread will never wait to


for a daemon thread, for its termination. This concept will be clear
once we examine the following program.

public class DaemonSample extends Thread {


public DaemonSample(String name) {
super(name);
}

public void run() {


int count = 0;
while (count < 10) { System.out.println("Number = " + count); count++;
try { sleep(500); } catch (InterruptedException e) {
e.printStackTrace(); } } }

public static void main(String[] args) {

DaemonSample sample = new DaemonSample("Thread1");

sample.setDaemon(true);

sample.start(); } }

In this case the sample.setDaemon(true) makes the child thread daemon.


So child thread is not starting (before starting the daemon child
thread, main thread exits).

So no numbers were printed in the console. If we remove the


sample.setDaemon(true) then numbers will be printed
8 Threading tutorial: ThreadPoolExecutor in Java

ThreadPools are useful when a number of tasks needs to be executed.


Dynamically we can create new threads for each tasks. But it is not
feasible for the JVM to manage all these threads.

In such situations a pool of threads can be used. This limits the


maximum number of threads within a limit. So it is easy for the JVM to
manage the threads. Either we can create our own threadpool or we can
use the ThreadPoolExecutor in java.util.concurrent.

ThreadPoolExecutor in java

A ThreadPoolExecutor in java manages a number of pooled threads.


Assume there are a number of tasks to be executed. These tasks can be
given to the ThreadPoolExecutor and each task will be executed by a
thread in the thread pool. For more details about ThreadPoolExecutor,
please see the Java doc.

Usually the tasks to be taken by any of the threads in the pool are
storing in a BlockingQueue. If all the threads are busy with tasks,
then the new task is storing in this queue. When a thread is free it
can take task from the queue.

ThreadPoolExecutor in java example

Now let us discuss this with an example. Here, we have four tasks.

1) First task is printing multiples of 10 from 1 to 50 with an


interval of 5 seconds

2) Second task is printing multiples of 10 from 50 to 100 with an


interval of 5 seconds

3) Third task is printing multiples of 5 from 100 to 150 with


interval of 5 seconds

4) Fourth task is printing multiples of 10 from 150 to 200 with an


interval of 5seconds
See the code snippet shown below. We are creating four runnable tasks.
And then creating a new thread pool executor with core pool size and
maximum pool size as 2.

ThreadPoolExecutor executorService = new ThreadPoolExecutor(2, 2, 10,


TimeUnit.MINUTES, queue)

The queue is the LinkedBlockingQueue instance to store the tasks. The


number 10 is the time to keep the additional threads(maximum pool size
core pool size) alive before its termination. TimeUnit is the unit
of the above time. So here the time is 10 minutes. But we are not
creating additional threads here, since core pool size and maximum
pool size are 10).

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolExecutorSample{

public ThreadPoolExecutorSample() {}

public static void main(String[] args) {

Runnable firstTask = new Runnable() {


int number = 0;

public void run() {


while (number < 50) { System.out.println("Thread :" +
Thread.currentThread().getName() + " Number = " + number); number =
number + 10; try { Thread.sleep(5000); } catch (InterruptedException
e) { e.printStackTrace(); } } } };

Runnable secondTask = new Runnable() {


int number = 50;

public void run() {


while (number < 100) { System.out.println("Thread :" +
Thread.currentThread().getName() + " Number = " + number); number =
number + 10; try { Thread.sleep(5000); } catch (InterruptedException
e) { e.printStackTrace(); } } } };
Runnable thirdTask = new Runnable() {
int number = 100;

public void run() {

while (number < 150) { System.out.println("Thread :" +


Thread.currentThread().getName() + " Number = " + number); number =
number + 10; try { Thread.sleep(5000); } catch (InterruptedException
e) { e.printStackTrace(); } } } };

Runnable fourthTask = new Runnable() {


int number = 150;

public void run() {

while (number < 200) { System.out.println("Thread :" +


Thread.currentThread().getName() + " Number = " + number); number =
number + 10; try { Thread.sleep(5000); } catch (InterruptedException
e) { e.printStackTrace(); } } } };

LinkedBlockingQueue queue = new LinkedBlockingQueue();


ThreadPoolExecutor executorService = new ThreadPoolExecutor(2, 2, 10,
TimeUnit.MINUTES, queue);
executorService.execute(firstTask);
executorService.execute(secondTask);
executorService.execute(thirdTask);
executorService.execute(fourthTask);

}
}

Now let us see the output. There are only two threads to execute four
tasks. So first two tasks will be taken first. Then after completion
each thread will take the next task available in the queue.

This can be well understood by analyzing the output. The thread status
can be well identified by using any profiler. If we are using newer
version of JDK, then the bin directory contains JVisualVM.exe.

Open it and profile our Java process. Then we can see the status of
each thread. After the four taks are over, the two threads are staying
idle. It can be well understood by watching the profiler.
Output

Thread: pool-1-thread-1 Number = 0

Thread: pool-1-thread-2 Number = 50

Thread: pool-1-thread-2 Number = 60

Thread: pool-1-thread-1 Number = 10

Thread: pool-1-thread-2 Number = 70

Thread: pool-1-thread-1 Number = 20

Thread: pool-1-thread-2 Number = 80

Thread: pool-1-thread-1 Number = 30

Thread: pool-1-thread-2 Number = 90

Thread: pool-1-thread-1 Number = 40

Thread: pool-1-thread-1 Number = 100

Thread: pool-1-thread-2 Number = 150

Thread: pool-1-thread-1 Number = 110

Thread: pool-1-thread-2 Number = 160

Thread: pool-1-thread-2 Number = 170

Thread: pool-1-thread-1 Number = 120

Thread: pool-1-thread-2 Number = 180

Thread: pool-1-thread-1 Number = 130

Thread: pool-1-thread-2 Number = 190

Thread: pool-1-thread-1 Number = 140


9 Threading tutorial: ThreadPool in Java

Suppose in an application, large number of tasks needs to be


completed. It is practically not possible to do all these tasks with
separate threads for each task.

Creating large number of threads in a Java process is very difficult


for the JVM to manage. The concept ThreadPool in Java is useful in
situations involving so many tasks. A pool of threads can be used for
completing those tasks. The number of threads will be limited in this
case.

ThreadPool in Java

Here there are a number of threads in the pool. Once a new task comes,
the task is adding to a queue. From the queue that task is taking by
any of the threads in the pool.

When all threads are busy with tasks, then the new tasks coming is
keeping in the queue. Those tasks will be taken by any of the
threads in the pool soon.

ThreadPool in Java example

Here, we are discussing the concept of thread pool with an example.


Java is providing a ThreadPoolExecutor in concurrent package to manage
pool of threads. If we are using that directly, the overburden of
creating and managing threads will be gone.

The first class given here is the ThreadPool.java. It is having a


LinkedBlockingQueue to keep the incoming tasks. It is having an array
of Service objects.

The Service object is nothing but a thread object. That also given
below as the second code snippet. ThreadPool is starting the threads.
Once a new task comes the task is passing to the execute method, where
the task is adding to the queue of ThreadPool and notifying all the
Service threads.

If any of the Service thread is waiting to get a task, the new task
is giving to that Service and it will be executed.

import java.util.concurrent.LinkedBlockingQueue;

public class ThreadPool {


private int poolSize = 0;
private LinkedBlockingQueue queue = null;
private Service[] services = null;

public ThreadPool(int size) {


this.poolSize = size;
services = new Service[size];
this.queue = new LinkedBlockingQueue();
startServices();

private void startServices() {


for (int i = 0; i < poolSize; i++) {
services[i] = new Service(queue);
services[i].start(); } }

public void execute(Runnable task) { synchronized (queue) {


queue.add(task); queue.notify(); } } }

Now let us see the Service.java. It is nothing but a thread object.


The ThreadPool.java class shown above has an array of Service objects.
These are threads which can access the same LinkedBlockingQueue of
ThreadPool.java. So the Service thread can take the task added in
ThreadPool.

import java.util.concurrent.LinkedBlockingQueue;

public class Service extends Thread {


private LinkedBlockingQueue queue = null;
private Runnable task = null;
public Service(LinkedBlockingQueue queue, String name) {
super(name);
this.queue = queue;
}

public void run() {


while (true) {
synchronized (queue) {
while (queue.isEmpty()) {
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
try {
task = (Runnable) queue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
task.run();
}
}
}

If there is no task in the queue, then the Service thread is waiting


on queue. Once a new task comes, Service thread moves out from the
wait and takes that task.

And then executes the task. Our task is Runnable but we are not
executing the task with start() method, because we are not going to
start a new thread for each Runnable, but executing the task in the
current service thread.

Now let us see the main class. The main class is creating a ThreadPool
instance with number of Services as 3. And creating four Runnable
tasks.

1) First task is printing multiples of 10 from 0 to 50


2) Second task is printing multiples of 10 from 50 to 100

3) Third task is printing multiples of 10 from 100 to 150

4) Fourth task is printing multiples of 10 from 150 to 200

Before printing the next number, a sleep time of 5 seconds is given.


It is to see the working correctly.

public class ThreadPoolMain {

public ThreadPoolMain() {}

public static void main(String[] args) {

ThreadPool pool = new ThreadPool(3);


Runnable firstTask = new Runnable() {
int number = 0;
public void run() {
while (number < 50) { System.out.println("Thread :" +
Thread.currentThread().getName() + ": Number = " + number); number =
number + 10; try { Thread.sleep(5000); } catch (InterruptedException
e) { e.printStackTrace(); } } } };

Runnable secondTask = new Runnable() { int number = 50; public void


run() { while (number < 100) { System.out.println("Thread :" +
Thread.currentThread().getName() + ": Number = " + number); number =
number + 10; try { Thread.sleep(5000); } catch (InterruptedException
e) { e.printStackTrace(); } } } };

Runnable thirdTask = new Runnable() { int number = 100; public void


run() { while (number < 150) { System.out.println("Thread :" +
Thread.currentThread().getName() + ": Number = " + number); number =
number + 10; try { Thread.sleep(5000); } catch (InterruptedException
e) { e.printStackTrace(); } } } };

Runnable fourthTask = new Runnable() { int number = 150; public void


run() { while (number < 200) { System.out.println("Thread :" +
Thread.currentThread().getName() + ": Number = " + number); number =
number + 10; try { Thread.sleep(5000); } catch (InterruptedException
e) { e.printStackTrace(); } } } };

pool.execute(firstTask);

pool.execute(secondTask);
pool.execute(thirdTask);

pool.execute(fourthTask); } }

Now let us see the output. Here three Service threads are starting. So
3 out of the four tasks will be taken. Once any of the service
finishes its task, it takes the remaining task.

When queue is empty the threads are waiting. The working can be well
understood if we use any Java profiler. If we are using newer versions
of jdk then the bin directory of JDK contains a JVisualVM.exe. if we
profile our application with VisualVM, we can see the status of each
thread in the pool).

Remember, this application is not exiting itself, because the Service


threads are executing for the whole time (because of the while(true)
in run() method).

Output

Thread: Service2: Number = 0

Thread: Service1: Number = 100

Thread: Service0: Number = 50

Thread: Service1: Number = 110

Thread: Service0: Number = 60

Thread: Service2: Number = 10

Thread: Service1: Number = 120

Thread: Service0: Number = 70

Thread: Service2: Number = 20

Thread: Service1: Number = 130

Thread: Service0: Number = 80

Thread: Service2: Number = 30

Thread: Service1: Number = 140


Thread: Service0: Number = 90

Thread: Service2: Number = 40

Thread: Service1: Number = 150

Thread: Service1: Number = 160

Thread: Service1: Number = 170

Thread: Service1: Number = 180

Thread: Service1: Number = 190

You can change the number of threads in the main method and you can
see the difference.
10 Threading tutorial: Thread deadlock in Java

Thread Deadlock is a situation which can occur in any Java application


which has multiple threads. In this section we are discussing the
concept of thread deadlock in java with suitable example.

Thread deadlock in java

Deadlock is a situation, when two or more threads are waiting each


other and hence blocked forever. Our application freezes in such a
situation.

If our application is a GUI based application, then the GUI will


freeze. The deadlock situation can be well understood with the help of
any profiler.

By inspecting the heap dump, it is possible to identify which all


threads are locked each other. If we are using newer versions of JDK,
then the JDK/bin contains the JVisualVM.exe.

It is the inbuilt profiler within the JDK. Just open the profiler and
profile our application which is suspecting for thread deadlock.
Then click on the heap dump option.

Thread deadlock in Java example

Let us see this with an example.

We have two threads. One thread for printing even numbers and the
other for printing odd numbers. Also we have two shared objects.

First thread is:

public class EvenThread extends Thread {


private Object sharedFirst = null;
private Object sharedSecond = null;
public EvenThread(String name, Object sharedFirst, Object
sharedSecond) {
super(name);
this.sharedFirst = sharedFirst;
this.sharedSecond = sharedSecond;

}
public void run() {
synchronized (sharedFirst) {
System.out.println("Thread " + getName() + " acquired lock on
sharedFirst");
synchronized (sharedSecond) {
System.out.println("Thread " + getName() + " acquired lock on
sharedSecond");
int num = 0;
while (num <= 100) { System.out.println("Even number = " + num); num =
num + 2; } } } } }

Now the second thread is:

public class OddThread extends Thread {


private Object sharedFirst = null;
private Object sharedSecond = null;
public OddThread(String name, Object sharedFirst, Object sharedSecond)
{
super(name);
this.sharedFirst = sharedFirst;
this.sharedSecond = sharedSecond;

public void run() {


synchronized (sharedSecond) {
System.out.println("Thread " + getName() + " acquired lock on
sharedSecond");
synchronized (sharedFirst) {
System.out.println("Thread " + getName() + " acquired lock on
sharedFirst");
int num = 1;
while (num <= 100) { System.out.println("Odd number = " + num); num =
num + 2; } } } } }

Now let us see the main to run the above threads:


public class DeadLockMain {

public DeadLockMain(){
}

public static void main(String[]args){

Object sharedFirst = new Object();


Object sharedSecond = new Object();

EvenThread evenThread = new


EvenThread("Even",sharedFirst,sharedSecond);
OddThread oddThread = new OddThread("Odd",sharedFirst,sharedSecond);
evenThread.start();
oddThread.start();
}
}

The deadlock scenario is explained below.

1) EvenThread acquires lock on sharedFirst.

2) OddThread acquires lock on sharedSecond.

3) EvenThread is trying to acquire lock on sharedSecond which is


locked for OddThread. So EvenThread is waiting for OddThread. Second
synchronized block of run() method in EvenThread.java.

4) OddThread is trying to acquire lock on sharedFirst which is locked


for EvenThread. So OddThread is waiting for EvenThread. Second
synchronized block of run() method in OddThread.java.

So both these threads are waiting each other. They will never come out
of that stage. The output makes the concept a bit more clear.

Output

Thread Even acquired lock on sharedFirst

Thread Odd acquired lock on sharedSecond


Two threads executes reaches in the first synchronized block. There
both the threads waiting each other. If you take the heap dump, then
the deadlock will be reported there. If we use any profiler then also
it is possible to identify the deadlock.

Resolving thread deadlock

If we have synchronized blocks inside another, then the order should


be given with proper care. Care should be taken if we call a
synchronized method from another synchronized method. Use synchronized
keyword when it is necessary only.
11 Threading tutorial: Starvation and livelock in Java

Starvation and LiveLock in Java are two issues those can affect the
smooth working of an application which involves many threads sharing
common resources.

Starvation and LiveLock in Java

Starvation

Suppose there are multiple threads in a Java process, all needs to get
lock on a particular object. Assume the first thread holds lock on the
shared object for a long time. For this entire time others threads
are waiting. Suppose the long duration thread is invoking very
frequently. So other threads will be blocked from accessing the shared
object. This situation is referred as starvation in muti-threading.

LiveLock

It is a situation in multi-threading when two or more threads are


unable to make any progress and they are not blocked each other. These
threads are responding to each other to finish the tasks, but no
progress is going to happen.

Das könnte Ihnen auch gefallen