Thread Synchronization

When multiple threads operate over same java object then there is a chance of data inconsistency problem hence Thread Synchronization came into picture.

  • Synchronized is the modifier applicable only for methods and blocks but not for classes and variables.
  • If multiple threads are trying to operate simultaneously on the same java object then there may be chance of data inconsistency problem, to overcome this problem we should go for synchronized keyword.
  • If a method or block declared as synchronized, then at a time only one thread is allowed to execute that method or block on the given object so that data inconsistency problem will be resolved.
  • The main advantage of synchronized keyword is we can resolve data inconsistency problems but the main disadvantage synchronized keyword is it increases waiting time of thread and creates performance problems. Hence if there is no specific requirement then it is not recommended to use synchronized keyword.
  • Internally synchronization concept is implemented by using lock, every object in java has a unique lock.
  • When ever we are using synchronized keyword then only lock concept will come into picture.
  • If a thread wants to execute synchronized method on the object first it has to get lock of that object, once thread got the lock of that object then it is allowed to execute any synchronized method on that object.
  • Once method execution completes automatically thread releases the lock. Acquiring and releasing lock internally is taken care by JVM and programmer not responsible for this activity.
  • While a thread executing synchronized method on a given method then the remaining threads are not allowed to execute any synchronized method simultaneously on the same object but remaining threads are allowed to execute non synchronized methods simultaneously.

Below example shows how all the 4 threads are executed one after another because of the synchronized keyword.

package com.demo1;

public class ThreadNameDemo {
	
	public static void main(String[] args) throws InterruptedException {
		TempThread temp = new TempThread();
		Thread t1 = new Thread(temp);
		Thread t2 = new Thread(temp);
		Thread t3 = new Thread(temp);
		Thread t4 = new Thread(temp);
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		System.out.println("Thread stopped");
	} 
}
class TempThread implements Runnable{
	@Override
	public synchronized void run() {
		try {
			for(int i=0; i<3;i++) {
				System.out.println(Thread.currentThread().getName()+" - "+i);
				Thread.sleep(10);
			}
		}catch(InterruptedException e) {
			System.out.println("InterruptedException has been caught : "+e);
		}
	}
}
  • While a thread executing synchronized method on an given object the remaining threads(executing same object) are not allowed to execute any other synchronized method simultaneously on the same object, but remaining threads are allowed to execute non synchronized methods simultaneously.
    Example Below :
package com.demo1;

public class ThreadDemo extends Thread{
	public static void main(String[] args) {
		Print p = new Print(2);
		new Thread(new PrintMultiplicationRunnable(p)).start();
		new Thread(new PrintSquareRunnable(p)).start();
		new Thread(new PrintAdditionRunnable(p)).start();
	}
}
class Print{
	int number;
	Print(int x){
		number = x;
	}
	public int getNumber() {
		return number;
	}
	public void setNumber(int number) {
		this.number = number;
	}
	void prinAdditionTables(int x) throws InterruptedException {
		int i;
		for(i=1;i<=10;i++) {
			System.out.println(x +" + "+i+" = "+x+i+" - non synchronized  method");
			Thread.sleep(500);
		}
	}
	synchronized void printMultiplicationTables(int x) throws InterruptedException {
		int i;
		for(i=1;i<=10;i++) {
			System.out.println(x +" x "+i+" = "+x*i+" synchronized method - 1 ");
			Thread.sleep(100);
		}
	}
	synchronized void printSquares(int x) throws InterruptedException {
		int i,j,temp;
		for(i=1;i<=10;i++) {
			temp=1;
			for(j=1;j<=x;j++) {
				temp = i * temp;
			}
			System.out.println(" Value : "+temp+" synchronized method - 2 ");
			Thread.sleep(100);
		}
	}
}
class PrintAdditionRunnable implements Runnable {
	Print p;
	PrintAdditionRunnable(Print p){
		this.p = p;
	}
	@Override
	public void run() {
			try {
				p.prinAdditionTables(p.getNumber());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
	}
}
class PrintMultiplicationRunnable implements Runnable{
	Print p;
	PrintMultiplicationRunnable(Print p){
		this.p = p;
	}
	@Override
	public void run() {
		try {
			p.printMultiplicationTables(p.getNumber());
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
class PrintSquareRunnable implements Runnable{
	Print p;
	PrintSquareRunnable(Print p){
		this.p = p;
	}
	@Override
	public void run() {
		try {
			p.printSquares(p.getNumber());
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

As you can see in the above example method 1 and method 2 are two different synchronized method of a class but both are executed one after another only because during an execution of a synchronized method object level lock is acquired by the thread and no other synchronized method of that object can be execute by any thread at that point of time. But all the non synchronized method are free to execute at any point of time no lock is required for it.

Note : Wherever we are performing update operation(Add/Remove/Delete/Replace) that changes the state of object we should be adding synchronized method to it.

Example 2 :

package com.demo1;

import java.util.stream.IntStream;

public class HelloThreadDemo {
	public static void main(String[] args) {
		Greet greet = new Greet();
		GreetThread t1 = new GreetThread(greet,"Tyson");
		GreetThread t2 = new GreetThread(greet,"Justin");
		GreetThread t3 = new GreetThread(greet,"Martin");
		t1.start();
		t2.start();
		t3.start();
	}
}

class Greet{
	synchronized public void wish(String name) {
		IntStream.range(0,10).forEach(x -> System.out.println(name +" "+x));
	}
}
class GreetThread extends Thread{
	Greet greet;
	String name;
	GreetThread(Greet greet,String name){
		this.greet = greet;
		this.name = name;
	}
	public void run() {
		greet.wish(name);
	}
}

If we are not declaring wish method as synchronized then all the three threads will be executed simultaneously the output will be some like this below.

Static Synchronized method

Class level lock : Every class in java has a unique lock which is nothing but class level lock.

If a thread wants to execute a static synchronized method then thread requires class level lock, once thread got class level lock then it is allowed to execute any static synchronized method of that class. Once method execution completes automatically thread releases the lock.

Important :

  • While a thread executing static synchronized method the remaining threads are not allowed to execute any static synchronized method since class level lock is already acquired by one of the method.
  • But remaining threads are allowed to execute the following method simultaniously
    • Normal static method
    • Synchronized instance methods
    • Normal instance methods.
package com.demo1;

import java.util.stream.IntStream;

public class HelloThreadDemo {
	public static void main(String[] args) {
 		GreetThread t1 = new GreetThread( new Greet(),"Tyson");
		GreetThread t2 = new GreetThread( new Greet(),"Justin");
		GreetThread t3 = new GreetThread( new Greet(),"Martin");
		t1.start();
		t2.start();
		t3.start();
	}
}

class Greet{
	public static synchronized void wish(String name) {
		IntStream.range(0,10).forEach(x -> System.out.println(name +" "+x));
	}
}
class GreetThread extends Thread{
	Greet greet;
	String name;
	GreetThread(Greet greet,String name){
		this.greet = greet;
		this.name = name;
	}
	public void run() {
		greet.wish(name);
	}
}

The methods to prevent Thread execution(Yield/Join/Sleep)

Yield Method

  • Yield method causes to pause the current executing thread to give the chance for waiting threads of same priority.
  • If there is no waiting thread or all waiting threads have low priority then same thread can continue its execution.
  • If multiple threads are waiting with same priority then which waiting thread will get the chance we cannot expect it depends on the thread scheduler.
  • The thread which is yielded when it will get the chance once again it depends on thread scheduler and we can predict it exactly.
  • If your schedular/processor does not support preemptive scheduling then yield method may not work on that platform.
public static native void yield();
public class ThreadNameDemo {
	public static void main(String[] args) {
		Thread t = new Thread(new TempThread());
		t.start();
		for(int i=0; i<10;i++) {
			Thread.yield();
			System.out.println("Main Thread : "+i);
		}
	} 
}
class TempThread implements Runnable{
	@Override
	public void run() {
		for(int i=0; i<10;i++) {
			Thread.yield();
			System.out.println("Child Thread : "+i);
		}
	}
}

Join Method

Case 1 : Main Thread Call join method on Child Thread Object (Main Thread waits for child thread to complete)

  • If a thread wants to wait until completing some other thread then we should go for join method.
  • For example : If a thread T1 wants to wait until completing T2 then T1 has to call T2.join()
  • If T1 executes T2.join() then immediately T will be entered into waiting state until T2 thread is completed.
  • Once T2 thread completes then T1 thread can continue its execution.
  • We can also ask a thread to wait for a thread for some fixed time, by passing the time parameter in the join() method.
  • If a Thread call a join() method on itself then the program will be stuck for ever in deadlock.
public final void join()  throws InterruptedException
public final void join(long milliseonds)  throws InterruptedException
public final void join(long milliseonds, int nanoseconds)  throws InterruptedException
package com.demo3;

public class ThreadNameDemo {
	public static void main(String[] args) throws InterruptedException {
		Thread t = new Thread(new TempThread());
		t.start();
		t.join(1000);
		for(int i=0; i<10;i++) {
			System.out.println("Main Thread : "+i);
		}
	} 
}
class TempThread implements Runnable{
	@Override
	public void run() {
		for(int i=0; i<10;i++) {
			try {
				Thread.sleep(300);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("Child Thread : "+i);
		}
	}
}

Output :

Child Thread : 0
Child Thread : 1
Child Thread : 2
Main Thread : 0
Main Thread : 1
Main Thread : 2
Main Thread : 3
Main Thread : 4
Main Thread : 5
Main Thread : 6
Main Thread : 7
Main Thread : 8
Main Thread : 9
Child Thread : 3
Child Thread : 4
Child Thread : 5
Child Thread : 6
Child Thread : 7
Child Thread : 8
Child Thread : 9

Case 2 : Child Thread class join method on main method. (Child Thread waiting for main Thread to complete.)

public class ThreadNameDemo {
	public static void main(String[] args) throws InterruptedException {
		Thread t = new Thread(new TempThread(Thread.currentThread()));
		t.join();
		for(int i=0; i<5;i++) {
			System.out.println("Main Thread : "+i);
		}
	} 
}
class TempThread implements Runnable{
	public static Thread mainThread;
	TempThread(Thread t){
		mainThread = t;
	}
	@Override
	public void run() {
		try {
			mainThread.join();
			for(int i=0; i<5;i++) {
				Thread.sleep(300);
				System.out.println("Child Thread : "+i);
			}
		}catch(Exception e) {
			System.out.println("Exception has been caught : "+e);
		}
	}
}

Output :

Main Thread : 0
Main Thread : 1
Main Thread : 2
Main Thread : 3
Main Thread : 4
Child Thread : 0
Child Thread : 1
Child Thread : 2
Child Thread : 3
Child Thread : 4

Case 3: Main Thread and child thread both waiting for each other to complete (Deadlock)

public class ThreadNameDemo {
	public static void main(String[] args) throws InterruptedException {
		Thread t = new Thread(new TempThread(Thread.currentThread()));
		t.start();
		t.join();
		for(int i=0; i<5;i++) {
			System.out.println("Main Thread : "+i);
		}
	} 
}
class TempThread implements Runnable{
	public static Thread mainThread;
	TempThread(Thread t){
		mainThread = t;
	}
	@Override
	public void run() {
		try {
			mainThread.join();
			for(int i=0; i<5;i++) {
				System.out.println("Child Thread : "+i);
			}
		}catch(Exception e) {
			System.out.println("Exception has been caught : "+e);
		}
	}
}

or you see the below example as deadlock

public class ThreadNameDemo {
	
	public static void main(String[] args) throws InterruptedException {
		Thread.currentThread().join();
		System.out.println("Hello Thread");
	}
}

Sleep Method

  • If a thread don’t want to perform any operation for a particular amount of time then we should go for sleep method.
  • Every sleep method throws Interrupted Exception which is checked exception hence when ever we are using sleep method it is mandatory to handle Interrupted Exception.
public static native void sleep(long milliseconds) throws InterruptedException
public static void sleep(long milliseconds, int nanoseconds) throws InterruptedException

public class ThreadNameDemo {

public static void main(String[] args) throws InterruptedException {
    for(int i=0; i<5;i++) {
        Thread.sleep(500);
        System.out.println("Main Thread : "+i);
    }
}

How a Thread can Interrupt another Thread

A Thread can interrupt a sleeping thread or waiting thread by using interrupt method of thread class.

  • A Thread can interrupt a sleeping thread or waiting thread by using interrupt method of thread class.
  • If thread is not in sleeping state or waiting state then there is no impact of interrupt calling.
public void interrupt();
public class ThreadNameDemo {
	
	public static void main(String[] args) throws InterruptedException {
		Thread t = new Thread(new TempThread());
		t.start();
		t.interrupt();
		System.out.println("Thread stopped");
	} 
}
class TempThread implements Runnable{
	@Override
	public void run() {
		try {
			for(int i=0; i<5;i++) {
				System.out.println("Child Thread : "+i);
				Thread.sleep(1);
			}
		}catch(InterruptedException e) {
			System.out.println("InterruptedException has been caught : "+e);
		}
	}
}

Thread priorities

Point to remember in case of Thread priorities

  • Valid range of Java Thread priorities is from 1 to 10
  • 1 is the MIN priority (Thread.MIN_PRIORITY)
  • 10 is the MAX priority (Thread.MAX_PRIORITY)
  • 5 is the NORMAL priority (Thread.NORM_PRIORITY)
  • The default priority of main thread is 5 for all other threads the default priority will be inherited from parent thread to the child thread.
public final int getPriority();
public final void setPriority(int p); //allowed values from 1 to 10
public class ThreadNameDemo {
	public static void main(String[] args) {
		Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
		Thread t = new Thread(new TempThread());
		t.setPriority(Thread.MAX_PRIORITY);
		t.start();
		IntStream.rangeClosed(1,10).forEach(x -> System.out.println(Thread.currentThread().getName()+" "+x));
	} 
}
class TempThread implements Runnable{
	@Override
	public void run() {
		IntStream.rangeClosed(1,10).forEach(x -> System.out.println(Thread.currentThread().getName()+" "+x));
	}
}

Getting and setting name of thread

Thread.currentThread() method will fetch the currently executing Thread object and then you can set or get the name of the thread using setName(<new name>), getName() method respectively. Sample below.

import java.util.stream.IntStream;

public class ThreadNameDemo {
	public static void main(String[] args) {
		new Thread(new TempThread()).start();
		IntStream.rangeClosed(1,10).forEach(x -> System.out.println(Thread.currentThread().getName()+" "+x));
	} 
}
class TempThread implements Runnable{
	@Override
	public void run() {
		Thread.currentThread().setName("Child thread");
		IntStream.rangeClosed(1,10).forEach(x -> System.out.println(Thread.currentThread().getName()+" "+x));
	}
}

Defining a Thread in java using Runnable interface

Defining a thread :

We can define a thread in the following two ways :
a. By extending Thread class
b. By implementing runnable interface.

By implementing runnable interface.

  • Runnable interface is present in java.lang package and it contains one method called public void run() method.
  • The major difference between Thread class and Runnable Interface is that Thread class is the class which has the ability to create Threads in java but Runnable Interface is just an interface which helps to define the job which has to be executed by a Thread using the run method.
  • We can pass an object of a class which implements Runnable interface to the constructor a Thread class object and call the Thread class’s start method to start a new child thread.
  • Since runnable interface is just used to create the job which has to be executed by a Thread we cannot specifiy the name of the thread using Runnable interface, we can give name to a thread when we pass the reference of the class that implements Runnable interface into the Thread constructor or by setName() method of the Thread class
    Thread t = new Thread(runnableObject,”My Thread Name”);
    t.setName(“My Thread Name”);
package com.demo2;

import java.util.stream.IntStream;

class MyRunnable implements Runnable{

	@Override
	public void run() {
		IntStream.range(1,10).forEach(x -> System.out.println("Child Thread : "+x));
	}
}

public class ThreadDemo {
	public static void main(String[] args) {
		Thread t = new Thread(new MyRunnable());
		t.start();
		IntStream.range(1,10).forEach(x -> System.out.println("Main Thread : "+x));
	}
}

Among the two ways to defining a thread, the implementing Runnable interface approach is suggest because the class implementing Runnable method still has a scope to extend another class but a class extending Thread class cannot support this functionality.

Defining a Thread in java by extending Thread class.

Defining a thread :

We can define a thread in the following two ways :
a. By extending Thread class
b. By implementing runnable interface.

By extending Thread class.

After extending a thread it is necessary to override the run method of the Thread class to define a job of the class.

package com.demo1;

import java.util.stream.IntStream;

public class MyThread extends Thread{ //Defining a Thread

	public void run() { //Job of a Thread
		IntStream.range(1,10).forEach(x -> System.out.println("Child Loop : "+x));
	}
}
class DemoRunningThread{
	public static void main(String[] args) { //Main Thread
		MyThread myThread = new MyThread(); //Thread instantiation
		myThread.start(); //Starting of a Thread
		IntStream.range(1,10).forEach(x -> System.out.println("Main Loop : "+x));
	}
}

Case 1 : Thread Scheduler

Thread Scheduler is a part of JVM, it is responsible to schedule threads If multiple threads are waiting to be executed then in which order they will be executed will be decided by Thread scheduler.The algorithm (SJF,FCFS,Round Robin) used by Thread scheduler differs from JVM to JVM. The output of the above program is not fixed it changes from JVM to JVM or from execution to execution, we cannot define which will be printed first.

Case 2 : Difference between thread.start() and thread.run()

In case of thread.start() a new thread will be created which will be responsible to execute out job but in case of thread.run() our run method will be executed like a normal method and a new thread will not be created.

Case 3 : Importance of Thread class start method

Thread class start method is responsible to register the thread with thread scheduler and all other mandatory activities. Hence without executing thread class start method there is not chance of starting a new thread in java due to this thread class start method is considered as heart of multi-threading.
Steps of Thread class’s start method
a. Register the thread with the Thread Schedular
b. Perform all other mandatory action.
c. Invoke the run method.

Case 4 : Overloaded run method

Overloading of run method is possible but thread.start() method will always call the empty parameter run() run method.Other overloaded run method with any number of arguments should be called explicitly.

Case 5 : Not overriding run method

We can have a class extend Thread class but not override the run method and still execute the program without any compilation or run time error because the Thread class has a run() method in its class with an empty implementation. It is highly recommended to override run method other wise it is better to not implement run method.

Case 6 : Overriding of start method.

In case when a class extends a thread class but also overrides the start() method then the Thread class’s start() method will not be called and a new thread will not be created. Just the contents of start() method of the child class which is extending the Thread parent class will be called.

Case 7 : super.start()

If super.start() method is called in the child class it can execute the start() method of the actual Thread class which will create the thread

package com.demo1;

import java.util.stream.IntStream;

public class MyThread extends Thread{ //Defining a Thread

	public void start() {
		super.start(); //Starting the Thread
		System.out.println("Start method");
	}
	
	public void run() { //Job of a Thread
		IntStream.range(1,10).forEach(x -> System.out.println("Child Loop : "+x));
	}
}
class DemoRunningThread{
	public static void main(String[] args) { //Main Thread
		MyThread myThread = new MyThread(); //Thread instantiation
		myThread.start(); //calling the start method of MyThread and not Thread class
		IntStream.range(1,10).forEach(x -> System.out.println("Main Loop : "+x));
	}
}

Case 8 : Thread Lifecycle

Note : Once you have started a thread using thread.start() method and again if you try to start the method we get exception IllegalThreadStateException

Introduction to Multithreading

Types of Multitasking

1.Processed based multitasking (Used by OS )
2.Thread based multitasking (Used by Programming Languages like Java)

What is Thread ?

  • A flow of execution is a Thread.
  • For every thread a separate individual job is present.

Use of multi threading in real world application

-To develop web server and application servers, were clients connect to application via web sever for each client a thread is created.

Where to use multi-threading concept?
-Where individual operations can be performed independently.

When compare with old languages implementing multithreading is much easier in java since java has rich multithreading API(Thread, Runnable,Group…..) and programmer is only required to perform 10% of the task is required by the programmer to perform 90% of the task is done by Java itself.

Thread Class constructors :

  1. Thread()
  2. Thread(String name)
  3. Thread(Runnable target)
  4. Thread(Runnable target, String name)
  5. Thread(ThreadGroup group, String name)
  6. Thread(ThreadGroup group, Runnable target)
  7. Thread(ThreadGroup group, Runnable target, String name)
  8. Thread(ThreadGroup group, Runnable target, String name, long stackSize)

Regex Questions :

Answers

  1. Find any text which has Letters which starts with Capital Letters only?(Example : Java)
  2. Find any words which does not contain character en in it? (Example : word “engine” is not be found in the search)
  3. Find repeated words which are together? (Exampel : “the the” word together should not appear )

Random Text Below for these questions

  1. Examples are the open source PCRE engine (used in many tools and languages like PHP), the .NET
    regular expression library, and the regular expression package included with version 1.4 and later of the Java
    JDK. I will point out to you whenever differences in regex flavors are important, and which features are
    specific to the Perl-derivatives mentioned above.
    Give Regexes a First Try
    You can easily try the following yourself in a text editor that supports regular expressions, such as EditPad
    Pro. If you do not have such an editor, you can download the free evaluation version of EditPad Pro to try
    this out. EditPad Pro’s regex engine is fully functional in the demo version. As a quick test, copy and paste
    the text of this page into EditPad Pro. Then select Search|Show Search Panel from the menu. In the search
    pane that appears near the bottom, type in «regex» in the box labeled “Search Text”. Mark the “Regular
    expression” checkbox, and click the Find First button. This is the leftmost button on the search panel. See
    how EditPad Pro’s regex engine finds the first match. Click the Find Next button, which sits next to the Find
    First button, to find further matches. When there are no further matches, the Find Next button’s icon will
    flash briefly.
    Now try to search using the regex «reg(ular expressions?|ex(p|es)?)» . This regex will find all
    names, singular and plural, I have used on this page to say “regex”. If we only had plain text search, we would
    have needed 5 searches. With regexes, we need just one search. Regexes save you time when using a tool like
    EditPad Pro. Select Count Matc1+1=2hes in the Search menu to see how many times this regular expression can
    match the file you have open in EditPad Pro.
    If you are a programmer, your software will run faster since even a simple regex engine applying the above
    regex once will outperform a state 1+1=2 of the art plain text search algorithm searching through the data five times.
    Regular
    expressions also
    reduce
    development time.
    With a regex
    engine, it takes
    only one line (e.g.
    in Perl, PHP, Java
    or .NET) or a
    couple of lines
    (e.g. in C using
    PCRE) of code to,
    say, check if the
    user’s input looks
    like a valid email
    address.

RegEx engines

Regular Expressions work behind the scenes using RegEx engines, there are mainly two types of RegEx engines text-directed(DNF) and regex-directed(NFA) engine.

There is an easy way to find which RegEx engine is your application using, using put the text “hello world” in your application and search for “hello|hello world” . If your application returns hello then your application is using a regex directed engine, if your application returns “hello world” as the result then it is using a text-directed engine.

regex-directed engine is always eager and will return the left most result even if a better match can be found later

When applying «cat» to “He captured a catfish for his cat.”, the engine will try to match the first token in the regex «c» to the first character in the match “H”. This fails. There are no other possible permutations of this regex, because it merely consists of a sequence of literal characters. So the regex engine tries to match the «c» with the “e”. This fails too, as does matching the «c» with the space. Arriving at the 4th character in the match, «c» matches „c”. The engine will then try to match the second token «a» to the 5th character, „a”. This succeeds too. But then, «t» fails to match “p”. At that point, the engine knows the regex cannot be matched starting at the 4th character in the match. So it will continue with the 5th: “a”. Again, «c» fails to match here and the engine carries on. At the 15th character in the match, «c» again matches „c”. The engine then proceeds to attempt to match the remainder of the regex at character 15 and finds that «a» matches „a” and «t» matches „t”.

The entire regular expression could be matched starting at character 15. The engine is “eager” to report a match. It will therefore report the first three letters of catfish as a valid match. The engine never proceeds beyond this point to see if there are any “better” matches. The first match is considered good enough.This is how a regex directed engine works.