Jump to content
xisto Community
AdityaKar

Article On Concurrency In Java

Recommended Posts

Article on Concurrency in JAVA

I've been writing this one for the last few days and I know this has turned out to be a long article but go through it you might find something in it for you. :P

 

Concurrency

 

A microprocessor can only execute 1 instruction at any point of time. Therefore to increase the productivity the concept of concurrency or parallelism is used. This is similar like you watch TV and also eat, sleep and also breathe etc. Therefore by using concurrency we can increase the throughput of the processor. But the way a processor handles concurrency is different than our body handles concurrency. The body has many different neurons to pass signals to each other and therefore support parallelism but since a processor donât have those and it can execute only 1 instruction at any point of time therefore parallelism is handled by software and sometimes hardware ( we will talk about it shortly ).

 

Concurrency through software

 

A software handled concurrency requires careful coding for the different resources and their availability. This can be done through a programming language that has a rich set of APIs for this purpose, however most concurrency APIs do need support from the target Operating System so careful choosing of a programming language should be done. The general APIs used are POSIX Thread Libraries (C/C++) and the JAVA Threading API. POSIX libraries are hard to use while java is easier to use however I donât think thereâs any portability issue.

 

Concurrency through hardware

 

Actually this is only an illusion. The one with software is also an illusion but for a single processor, for multiple processor systems concurrency actually can take place. If anyone has idea about pipelining they would know about this. This kind of concurrency technique is implemented with use of hardware and software (compiler) in which the logic for implementing it is hardwired (canât be changed) into the processor itself. However this is another way in which the throughput of the processor can be increased but it is very much complicated and optimizations from compiler are often necessary in association with careful coding by the programmer himself to remove hazards and stalling as much as possible. Furthermore all the instructions canât be pipelined (I think!) . So this is very restrictive but can be quite fast. In this tutorial we will only consider software techniques for handling concurrency.

 

 

Basic Thread Model

 

For multiprogramming Operating Systems it is possible to run multiple programs concurrently but at any point of time the processor is working on only one of them. This time is so small that to us it looks like things are happening concurrently. The simplest way to do this job is to switch between the programs. There are different policies by which this switch between the programs can be performed and the OS handles. This switch between the programs requires quite a few amount of resources so full executable program are also called heavy weight processes. But the switch between the programs is not the basic switching mechanism , for example we have all played games, worked on programs with some animation or banner moving around it. These tasks are embedded within the program itself to be executed concurrently with other active components of the program like waiting for an input with the banner also flashing. These tasks are called Thread. So a thread is a basic unit of code that can be switched among other threads of a program which is in execution. Threads are also called light weight processes. Since few resources are required for switching between the threads. The resources that Iâm talking about are registers, data etc (you can find it in any OS book).

 

 

Javaâs Support for Concurrency

 

Java provides the Threading API for managing concurrent code. The class used for this purpose is java.lang.Thread. This class has all the functionality needed to implement threads and thus therefore acts as a base class for all the concurrent task handling classes. The Thread class has a method run () (public void run ()). All the concurrent code is written inside the run () method. The following example shows how

 

public class MyThreads extends Thread{			int threadCount=10;	int threadNumber;public MyThreads (int threadNumber)	{		this.threadNumber=threadNumber;System.out.println (âThread number â+ threadNumber+âis now createdâ);		this.start ();	}	public void run ()	{		while (true){System.out.println (this);threadCount--;if (threadCount==0) break;		}	}	public String toString () // This is required for use in run ()	{	return âThread Numberâs â+ threadNumber +âcount value= â+ threadCount;	}	public static void main (String [] args)	{		for (int i=0; i<10; i++)		new MyThreads ();	}}

The above programâs description is given as below.

 

We have created a class named MyThreads which is used to make 10 threads of concurrent execution. The threads are created inside of the main method. Just extending from the Thread class doesnât mean that threading will take place, to make sure the start () method of the Thread class is called. This method initiates the thread and in turn calls the run () method. Usually run () is coded with an infinite loop and then break out of it when a given condition occurs. In our case we break out of the run () when a threadâs counter goes to 0.When run () is over the thread is also complete. It is important to note that unless start () method is called you canât initiate or start a thread. Also calling run () directly from the thread object wonât help so start () has to be called if threading is to take place.

 

NOTE: Many believe that sleep () method is required for threading. This is not true as can be seen from the above program. sleep () is useful when we need to temporarily halt a thread for some reason however its not necessary to use sleep () while writing threaded code. Also since threads are handled by the OS in a different way than variables and other objects they are NOT garbage collected automatically i.e. there is a reference to these objects somewhere (like in above example new MyThreads (i) these threads wonât be garbage collected even if they donât have any reference variable attached to them). To make sure that they are garbage collected we need to assign null to the reference which also kills the corresponding thread.

 

 

Controlling Concurrency

 

Concurrency can be controlled either by using yield () or by using the sleep () methods. sleep () just suspends the thread for a specified duration DURING WHICH IT STILL HOLDS THE CPU if it was in execution, while yield () relinquishes the cpu to some other thread waiting in the queue. Therefore sleep () causes waste of time and therefore should be used with precautions as it can slow down the processing of the program. The following examples show their use.

 

Example 1 modified for sleep ()public class MyThreads extends Thread{			int threadCount=10;	int threadNumber;public MyThreads (int threadNumber)	{		this.threadNumber=threadNumber;System.out.println (âThread number â+ threadNumber+âis now createdâ);		this.start ();	}	public void run ()	{		while (true){System.out.println (this);threadCount--;try{	sleep (10); // This method throws an  //exception which has to be //handled}catch (InterruptedException){	System.out.println (âThread â+threadNumber+âis Interruptedâ);}if (threadCount==0) break;		}	}	public String toString ()	{	return âThread Numberâs â+ threadNumber +âcount value= â+ threadCount;	}	public static void main (String [] args)	{		for (int i=0; i<10; i++)		new MyThreads ();	}}Example 1 modified for yield ()public class MyThreads extends Thread{			int threadCount=10;	int threadNumber;public MyThreads (int threadNumber)	{		this.threadNumber=threadNumber;System.out.println (âThread number â+ threadNumber+âis now createdâ);		this.start ();	}	public void run ()	{		while (true){System.out.println (this);threadCount--;if (threadCount==0) break;yield (); // This will halt temporarily this thread//and allows some other thread to use //CPU.		}	}	public String toString ()	{	return âThread Numberâs â+ threadNumber +âcount value= â+ threadCount;	}	public static void main (String [] args)	{		for (int i=0; i<10; i++)		new MyThreads ();	}}

Daemon Threads

 

These are the threads which have no life of their own. That is they can only remain active until a program is finished or they finish before the main program. These threads are usually those who do their job in background of the main program and their existence is forbidden when the main program terminates. Thus a program is over when there are no more NON-Daemon threads pending. The daemonhood of a thread can be set by using the methods setDaemon () (public void setDaemon (boolean)) and can be tested using isDaemon () (public boolean isDaemon ()).Example is shown below

 

class DaemonThread extends Thread{	static int daemonCreated;	public DaemonThread ()	{		System.out.println (âDaemons Created till now=â+ (++daemonCreated));	this.setDaemon (true);	this.start ();	}	public void run ()	{		while (true)		{			System.out.println (âDaemons are left =â+daemonCreated);		}	}}public class ThreadEX2 {	public static void main (String [] args) throws Exception	{		for (int i=0; i<100; i++)		{			new DaemonThread ();			sleep (100); //let JVM handle exception		}	}}

Setting Priorities among Threads

 

This is generally required when we have some task that requires more attention by the CPU because of its importance in the application although it must still run in parallel with all other threads. This can be done using the setPriority () method of the Thread class. The JAVA rates priorities on a scale of 0-10 with 0 having the least priority and 10 the max priority. These are also defined as static final constants in Thread class. These are MAX_PRIORITY, MIN_PRIORITY and NORM_PRIORITY. Any other priority can be calculated by using these three defined constants. The syntax of setPriority is <thread object>. setPriority (<int priority>).

 

Example: Try an example by creating different threads with different priorities and see how CPU handles the threads then.

 

 

Another way to Threaded Code

 

We can also write threaded code by not extending our class from the Thread class but by implementing the Runnable interface. This is required when our class has already extended some other class say JFrame for example and now we wish to add some threaded code to this class. Since JAVA doesnât support multiple base classes therefore an interface comes in handy. Even class Thread implements the Runnable interface.

 

To write threaded code this way we need to create a thread object with the Runnable object as its parameter and then call the start () method of Thread class. Example is shown below:

 

public class RunnableCodeExample implements Runnable{//This class is now a Runnable object also since it //implements the Runnable interface. Remember the //inheritance rule of up casting.Thread myThread;		public RunnableCodeExample ()	{myThread=new Thread (this); // a new Thread//object is created with the Runnable object as itâs //argument. Since the object of this class is Runnable //therefore we give the argument as this in the // constructor of Thread.			myThread. start ();	}	public void run ()	{		int i=0;		while (i! = 200)		{			System.out.println (âI =â+i);			++i;		}	}	public static void main (String [] args)	{		new RunnableCodeExample ();	}}

In the above program first the RunnableCodeExample is made to be an object of type Runnable by implementing Runnable interface. Now Thread class requires a Runnable object. A Runnable object is nothing but a class which implements the Runnable interface and thus has the run () method defined for the Thread class. Thereâs just a single method in this interface so we need to define this only.

 

PS: As an example you can try to make a frame (import javax.swing.*) with some controls and add to the same class a non-changeable display which shows the time / generates some random numbers through a separate Thread. You can also try to make this thread a daemon.

Also itâs a good practice to extend from the Thread class if you can and implement the Runnable interface in case you canât. However if you intend to write some general purpose thread then you should use Runnable and let the end user programmer do the threading and start the thread. That is you just provide a Runnable object to the programmer.

 

Sharing Resources

 

By running the code above and writing some code on your own up to this point of time. However as you can see the threads run wildly unless they are control. But why should we control threads? Well its not needed always for example when to tasks run mutually exclusive of each other thereâs no need for controlling threads, like a thread displaying banner and a thread displaying time may not require controlling and thus can be let run wild without controlling. However if suppose they both try to access same resource and change itâs state than a conflict may arise. For example consider two/ more threads trying to write to same file, without some control this will be disastrous.

 

Mutual Exclusiveness of Threads

 

For threads to be controlled or access the resources available in synchronized manner the concept of mutual exclusiveness is used. This principle states that a thread has exclusive access to the resource and any other thread trying to access the same resource is denied and forced to wait. This concept is implemented by use of monitors. A monitor is a data structure that holds the accessing information of the resource and thus therefore can be reused. The mutual exclusive property is enforced at the monitor boundary since thereâs only 1 monitor for each available resource and the thread which has the monitor locked can have exclusive access rights to that resource. All other threads trying to access that resource are forced to wait until the monitor is freed by the thread that owned it and acquired by some other waiting thread. This way of handling threads is also more feasible since it allows a thread to use a resource as much as it wants to till it holds the monitor. Once the monitor of a resource is freed one of the threads in the waiting queue is allowed to capture / acquire the lock on the monitor and use it.

 

PS: Threads are synchronized on the same OBJECT / RESOURCE. Remember this!

 

The synchronized keyword is used to synchronize the code and the methods wait (), notify () and notifyAll () are used to control and pass messages to the synchronized code. An example of this is shown below.

 

We are generating even and odd numbers in separate threads, but the order of generation should be 1 even followed by 1 odd or vice versa. Therefore controlling of threads is required.

 

class EvenOddGenerator // This is the resource type.{private int oddCount;	private int evenCount;	private int startCount;		private boolean semaphore;		public EvenOddGenerator (int count,int startCount)	{		oddCount=count;		evenCount=count;		this.startCount=startCount;	}	/*This code is synchronized and therefore requires a monitor to access it*/	public synchronized void oddGenerator ()	{		for (int i=startCount; i<oddCount+startCount; i++)		{			if (semaphore==true)			{				try 				{					wait ();				}				catch (Exception e)				{				}			}						if (i%2!=0)			{				System.out.println("From Odd Generator ODD number="+i);				semaphore=true;				notifyAll ();			}					}		System.out.println ("ODD Generator is Over!!");		semaphore=true;		notifyAll ();	}/*This code is synchronized therefore requires a monitor to access it*/		public synchronized void evenGenerator ()	{		for(int i=startCount;i<evenCount+startCount;i++)		{			if (semaphore==false)			{				try				{					wait ();				}				catch(Exception e)				{				}			}						if(i%2==0)			{				System.out.println("From Even Generator EVEN number="+i);				semaphore=false;				notifyAll();			}		}		System.out.println("EVEN Generator is Over!!");		semaphore=false;		notifyAll();	}}/*This is some thread which uses the resource. Remember our resource was EvenOddGenerator*/class EvenGenerator extends Thread{		EvenOddGenerator eoG; // This is the resource to use		public EvenGenerator(EvenOddGenerator eoG)	{		this.eoG=eoG;		this.start();	}		public void run()	{		eoG.evenGenerator();	}	}/*This is some thread which uses the resource. Remember our resource was EvenOddGenerator*/class OddGenerator extends Thread{	EvenOddGenerator eoG; //This is the resource to use	public OddGenerator(EvenOddGenerator eoG)	{		this.eoG=eoG;		this.start();	}		public void run()	{		eoG.oddGenerator();	}}public class SynchronizedExample{	public static void main(String [] args)	{		EvenOddGenerator eoG= new EvenOddGenerator(11,100); // create a single resource	/*The new threads will now access the same single resource in a synchronized manner.*/	new OddGenerator(eoG); //argument is same resource	new EvenGenerator(eoG);//argument is same resource	}}

This example demonstrates the use of wait, notify and notifyAll methods. These methods can ONLY BE CALLED from a synchronized block of code otherwise you will get an exception. The purpose of these methods is as described below:

 

Wait (): This method just makes a thread halt with CPU also being taken away from the thread from which this is called. Therefore any other thread(s) waiting in queue may get the CPU for execution. A thread which is waiting must be notified by some other thread in execution. This makes the waiting thread a part of the ready queue (waiting to get its hand on the CPU). A thread in which wait () is called is also called a blocked thread and only some other thread in execution may wake it up, however a thread can block itself while itâs running.

 

Notify (): This method makes the thread that called the wait () method recently a part of the ready queue. That is it only wakes up only 1 thread that was blocked.

 

NotifyAll (): This method wakes up all the threads which were blocked and makes them part of the ready queue.

 

PS: THE SYNCHRONIZED METHODS CAN ONLY BE CALLED BY A THREAD WHICH CURRENTLY HOLDS THE MONITOR,ALL OTHER THREADS ARE FORCED TO WAIT EVEN IF THEY WISH TO CALL A DIFFERENT METHOD FROM THE ONE USED BY THE THREAD IN EXECUTION. For ex: in above example if EvenGenerator is the Thread in execution and holds the monitor only it can access both the synchronized methods the other thread canât, even if they call different methods like above. However non synchronized methods can be called since they donât require a monitor.So therefore when you need to do synmchronization just make a class(define a RESOURCE ) and put all those methods that are synchronized. Make an object of this class (Actually make a resource now ) and share this object among threads to achieve synchronization.

Sometimes itâs needed that some part of the method is available to all the threads in execution however some part is available to only that thread which currently holds the monitor for the resource. Therefore concept of synchronized blocks is used. A synchronized block is same as a synchronized method except that some part of that method may be accessed by any thread. Since a resource is needed therefore syntax of synchronized block is

Method declaration (without synchronization keyword)

//âŚâŚcode

 

synchronized (<synchronized resource>)

{

âŚâŚâŚâŚ synchronized code

}

 

Some Questions that you may want to try outâŚâŚ

 

1.) Create 500 threads that do nothing just write an infinite loop in the run method. Code for the finalize method and show how many threads have been garbage collected. Donât assign reference to any so that garbage collector is called. You may also try to call the garbage collector explicitly what happens then?

2.) Write a program to add odd numbers and even numbers in separate threads. The threads should be supplied the count of numbers to be added and a start count.

3.) Write a program to add numbers divisible by either 4 or 6 in separate threads. The threads should be supplied the same info as in the above program. Note this is different from above since a number can be divisible by 4 and 6 at the same time.

4.) Try the producer consumer problem. Is there any other way to do this problem? If there is why not use it in all synchronization problems? (Hint look in I/O streams to find the answer).

5.) Implement a multithreaded Server/Socket application which can handle multiple connections simultaneously.

 

Server/Socket Programming

 

Java provides a way to handle interconnections between computers through the use of its network API. The classes described here are part of the java.net package.

 

Java.net.ServerSocket this class defines a server. This class has all the functionality needed to implement a network connection and create a server side implementation. The constructor of this class takes a port as parameter. This port is then used to establish connections with the clients. Server is created as

 

/*this throws an exception which must be dealt with in case a ServerSocket at the port specified couldnât be made. Also make sure the port number is above 1000 since below that the OS uses for different purposes so Java might not be able to create a ServerSocket there*/

 

ServerSocket server= new ServerSocket (int port);

 

Once a server is created successfully you need to make the server listen for connections at the port. This is done by the accept () method of ServerSocket class. The accept () method is blocking therefore it will wait for the connection to occur. On successful connection it returns the client as a Socket object.

 

Socket client= server. accept ();

 

Once a connection is established the messaging can be done by acquiring the input/ output streams of the client and the server components. This can be done using the getInputStream () and getOutputStream() of the Socket class.

 

In order to establish a multithreaded server you must listen for connections more than once and as soon as the connection is made a separate thread must be made to handle the messaging. Therefore something like this should be done in the server side coding.

 

While (true)

{

Socket client= server. accept () ;

new ClientThread(client);

}

 

This ClientThread is what you need to code. We have passed the Socket object in this because the thread must have some way of getting the I/O streams. You can also pass I/O streams as parameters but a Socket object has a bit more info like the InetAddress etc, look up the JDK Docs.

 

A client side coding just requires to make a connection to the server which is running. This can be done using the Socket class like this.

 

/*This also throws an exception if the Server is not present/connection isn't made for any reasons*/

 

Socket client=new Socket(âURLâ, int port);

 

The URL is a string which tells the location of the server and the port is where the server is listening for the connections. This is same as the port given in the ServerSocket while creating server. For testing on the same PC you can use localhost or a fully qualified InetAddress. Once this is done you can pass messages to server and server can message to you. But you must understand the I/O streams for implementing this thing. For any methodâs description look up JDK docs. The commonly used functions are as follows

 

InetAddress.getByName (âString urlâ);

ObjectOutputStream.writeObject(Object);

Object ObjectInputStream.readObject();

 

Similarly for other I/O streams and Readers. Readers are useful only when strings are sent. This means pure Strings and not anything wrapped inside your object. Otherwise readObject () and writeObject () must be used. Also in case you are using your own objects for message passing make sure they are serialized so that you can read them exactly on the other end.

 

The class Socket is not Serializable so canât put it inside your class that you wish to make serializable. It wonât work.

PS: To find out wether a class is serializable use the serialver tool provided by JDK. On the command type serialver <fully qualified class name> if the class is serializable it will show a serializable number for that class otherwise a string that the class is not serializable. Example use serialver java.net.Socket and use serialver java.util.Vector.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

Terms of Use | Privacy Policy | Guidelines | We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.