Date
Date
Thread Synchronization
1. Write a Java program to demonstrate “synchronized” block
2. Write a Java program to demonstrate “synchronized” method
3. Write a Java program to demonstrate to simulate
concurrency(inthread communication) in java ( use wait(),notify()
methods)
4. Develop an application to simulate Producer Consumer problem using
multithreading
5. Write a simulation program for the fruit market. The farmer will be
able to produce different types of fruits (apple, orange, grape, and
watermelon), and put them in the market to sell. The market has
limited capacity and farmers have to stand in a queue if the
capacity is exceeded to sell their fruits. Consumers can come to
the market any time and purchase their desired fruits; and if the
fruits they want to buy runs out, they are willing to wait until the supply
of that kind is ready. (Hint: implementing this market will encounter the
producer and consumer problem, and it probably needs multiple buffers for
different kinds of fruits).
Annotations(Built-in annotations)
1. Write a Java program to demonstrate ‘@override’ annotation
@Override – When we want to override a method of Superclass, we should use this
annotation to inform compiler that we are overriding a method. So when superclass
method is removed or changed, compiler will show error message
2. Write a Java program to demonstrate ‘@Deprecated’ annotation
when we want the compiler to know that a method is deprecated, we should
use this annotation. Java recommends that in javadoc, we should provide
information for why this method is deprecated and what is the
alternative to use
/**
* @deprecated
* reason for why it was deprecated
*/
@Deprecated
public void showDeprecatedMessage(){
System.out.println("This method is marked as deprecated");
}
@Deprecated
}
@SuppressWarnings("deprecation")
mde.showDeprecatedMessage();
}
Incase if you don't want to get any warnings from compiler for the known things, then you can
use @SuppressWarnings annotation. For example, you are calling deprecated method, and you
know that it is deprecated, to avoid compiler warnings, user @SuppressWarnings annotation.
Interthread Communication
wait
Object wait methods has three variance, one which waits indefinitely for any other thread to call
notify or notifyAll method on the object to wake up the current thread. Other two variances puts
the current thread in wait for specific amount of time before they wake up.
notify
notify method wakes up only one thread waiting on the object and that thread starts execution.
So if there are multiple threads waiting for an object, this method will wake up only one of them.
The choice of the thread to wake depends on the OS implementation of thread management.
notifyAll
notifyAll method wakes up all the threads waiting on the object, although which one will process
first depends on the OS implementation.
These methods can be used to implement producer consumer problem where consumer threads
are waiting for the objects in Queue and producer threads put object in queue and notify the
waiting threads.
1. synchronized keyword is used for exclusive accessing.
2. To make a method synchronized, simply add the synchronized keyword to its declaration.
Then no two invocations of synchronized methods on the same object can interleave with
each other.
3. Synchronized statements must specify the object that provides the intrinsic lock. When
synchronized(this) is used, you have to avoid to synchronizing invocations of other
objects' methods.
4. wait() tells the calling thread to give up the monitor and go to sleep until some other
thread enters the same monitor and calls notify( ).
5. notify() wakes up the first thread that called wait() on the same object.
Example:
Message.java
A java class on which threads will work and call wait and notify methods.
Waiter.java
A class that will wait for other threads to invoke notify methods to complete it’s
processing. Notice that Waiter thread is owning monitor on Message object using
synchronized block.
public class Waiter implements Runnable{
@Override
public void run() {
String name = Thread.currentThread().getName();
synchronized (msg) {
try{
System.out.println(name+" waiting to get notified at
time:"+System.currentTimeMillis());
msg.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(name+" waiter thread got notified at
time:"+System.currentTimeMillis());
//process the message now
System.out.println(name+" processed: "+msg.getMsg());
}
}
Notifier.java
A class that will process on Message object and then invoke notify method to wake up threads
waiting for Message object. Notice that synchronized block is used to own the monitor of
Message object.
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name+" started");
try {
Thread.sleep(1000);
synchronized (msg) {
msg.setMsg(name+" Notifier work done");
msg.notify();
// msg.notifyAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
InterThreadCommunicationDemo
Test class that will create multiple threads of Waiter and Notifier and start them.
Producer
1. Check if Buffer is full or not. If full, then wait() for buffer items to get consumed.
Consumer
1. Check if Buffer has items. If empty, then wait() for buffer to get filled.
Example #1
class Q
{
int n;
boolean valueSet=false;
synchronized int get()
{
if(!valueSet)
try
{
wait();
}
catch(InterruptedException e)
{
System.out.println("Interrupted Exception caught");
}
System.out.println("Got:"+n);
valueSet=false;
notify();
return n;
}
synchronized void put(int n)
{
if(valueSet)
try
{
wait();
}
catch(InterruptedException e)
{
System.out.println("Interrupted Exception caught");
}
this.n=n;
valueSet=true;
System.out.println("Put:"+n);
notify();
}
}
class Producer implements Runnable
{
Q q;
Producer(Q q)
{
this.q=q;
new Thread(this,"Producer").start();
}
public void run()
{
int i=0;
while(true)
{
q.put(i++);
}
}
}
class Consumer implements Runnable
{
Q q;
Consumer(Q q)
{
this.q=q;
new Thread(this,"Consumer").start();
}
public void run()
{
while(true)
{
q.get();
}
}
}
class ProdConsDemo
{
public static void main(String[] args)
{
Q q=new Q();
new Producer(q);
new Consumer(q);
System.out.println("Press Control-c to stop");
}
} class Q
{
int n;
boolean valueSet=false;
synchronized int get()
{
if(!valueSet)
try
{
wait();
}
catch(InterruptedException e)
{
System.out.println("Interrupted Exception caught");
}
System.out.println("Got:"+n);
valueSet=false;
notify();
return n;
}
synchronized void put(int n)
{
if(valueSet)
try
{
wait();
}
catch(InterruptedException e)
{
System.out.println("Interrupted Exception caught");
}
this.n=n;
valueSet=true;
System.out.println("Put:"+n);
notify();
}
}
class Producer implements Runnable
{
Q q;
Producer(Q q)
{
this.q=q;
new Thread(this,"Producer").start();
}
public void run()
{
int i=0;
while(true)
{
q.put(i++);
}
}
}
class Consumer implements Runnable
{
Q q;
Consumer(Q q)
{
this.q=q;
new Thread(this,"Consumer").start();
}
public void run()
{
while(true)
{
q.get();
}
}
}
class ProdCons
{
public static void main(String[] args)
{
Q q=new Q();
new Producer(q);
new Consumer(q);
System.out.println("Press Control-c to stop");
}
}
Example #2
import java.util.*;
class Buffer {
private int data;
private boolean empty;
public Buffer()
{
this.empty = true;
}
/*Consumer */
class Consumer extends Thread {
private Buffer buffer;
p.start();
c.start();
}
}
Example #2
class BankQueue {
int nextToGive=0, nextToServe=0;
synchronized int nextNumberToCustomer() {
notify();
return ++nextToGive;
}
synchronized int nextToServe() throws InterruptedException{
if (!(nextToServe<nextToGive)){
System.out.println("Waiting");
wait();
}
return ++nextToServe;
}
}
3) Runtime instructions: We can define annotations to be available at runtime which we can access
using java reflection and can be used to give instructions to the program at runtime.
Annotations basics
An annotation always starts with the symbol @ followed by the annotation name. The symbol @
indicates to the compiler that this is an annotation.
@Override
void myMethod() {
//Do something
}
What this annotation is exactly doing here is explained in the next section but to be brief it is
instructing compiler that myMethod() is a overriding method which is overriding the method
(myMethod()) of super class.
Built-in Annotations in Java
Java has three built-in annotations:
@Override
@Deprecated
@SuppressWarnings
1) @Override:
While overriding a method in the child class, we should use this annotation to mark that method.
This makes code readable and avoid maintenance issues, such as: while changing the method
signature of parent class, you must change the signature in child classes (where this annotation is
being used) otherwise compiler would throw compilation error. This is difficult to trace when
you haven’t used this annotation.
Example:
@Override
public void justaMethod() {
System.out.println("Child class method");
}
}
I believe the example is self explanatory. To read more about this annotation, refer this article:
@Override built-in annotation.
2) @Deprecated
@Deprecated annotation indicates that the marked element (class, method or field) is deprecated
and should no longer be used. The compiler generates a warning whenever a program uses a
method, class, or field that has already been marked with the @Deprecated annotation. When an
element is deprecated, it should also be documented using the Javadoc @deprecated tag, as
shown in the following example. Make a note of case difference with @Deprecated and
@deprecated. @deprecated is used for documentation purpose.
Example:
/**
* @deprecated
* reason for why it was deprecated
*/
@Deprecated
public void anyMethodHere(){
// Do something
}
Now, whenever any program would use this method, the compiler would generate a warning. To
read more about this annotation, refer this article: Java – @Deprecated annotation.
3) @SuppressWarnings
This annotation instructs compiler to ignore specific warnings. For example in the below code, I
am calling a deprecated method (lets assume that the method deprecatedMethod() is marked with
@Deprecated annotation) so the compiler should generate a warning, however I am using
@@SuppressWarnings annotation that would suppress that deprecation warning.
@SuppressWarnings("deprecation")
void myMethod() {
myObject.deprecatedMethod();
}