Beruflich Dokumente
Kultur Dokumente
Overview
Multi-threading in Java
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.
int count = 0;
public ThreadSample() {}
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().
public ThreadMain() {}
}
}
Now let us see the output.From the output we can clearly understand
the concept of threading by extending Thread class.
Output
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 RunnableMain() {}
Now let us see the output.It will be exactly the same as that of the
previous example.
Output
A thread goes through various stages in its entire life time. The
stages are listed here.
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().
public NumericCounter() {}
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.
Output
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.
Now let us verify the output. The output may be different in different
environments. But it can give a correct idea.
Output
The above explained classes can be modified for verifying the result.
public NumericCounter() {}
Output
3)synchronized block
synchronized(emp){
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() {}
Output
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.
int oddNumber = 1;
private Object shared = null;
public Main(){}
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.
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
int number = 0;
public FirstThread(String name) {
super(name);
}
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 {
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 Main(){}
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
public 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
Daemon threads are supporting threads those are running at the back
ground. These threads are usually intended to give support to other
threads.
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.
sample.setDaemon(true);
sample.start(); } }
ThreadPoolExecutor in java
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.
Now let us discuss this with an example. Here, we have four tasks.
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public ThreadPoolExecutorSample() {}
}
}
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
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.
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;
import java.util.concurrent.LinkedBlockingQueue;
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.
public ThreadPoolMain() {}
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).
Output
You can change the number of threads in the main method and you can
see the difference.
10 Threading tutorial: Thread deadlock in Java
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.
We have two threads. One thread for printing even numbers and the
other for printing odd numbers. Also we have two shared objects.
}
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; } } } } }
public DeadLockMain(){
}
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
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
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