Contents

Exploring Threads

Hi there! Hope you are doing good. I always had this fear of certain niche topics in software engineering which keep on bothering me every now and then (M kinda noob ๐Ÿผ). Multi-threading is one such topic.

So hence I have decided to face my inner-fears ๐Ÿ’ช and create a series of posts which will help me and others with similar fears to understand these topics in an easier way. This will also serve as reference notes.

  • Threads essentially allow us to solve computational problems by dividing the larger problem into smaller parallelized tasks. These tasks can run asynchronously and in a non-blocking fashion. Threads are especially useful in boosting performance โšก in multi-core systems.
  • Threads are often called as light-weight processes. Creating a new thread has a lesser memory foot-print as compared to creating a new process.
  • Every process has atleast has one thread(main thread). Using the main thread we can create child threads as per our needs.
  • Threads share resources of the parent process like memory space. Hence, data consistency can be an issue.
  • There are mainly two ways in which you can create threads in java:
  • One way to create a thread is to extend the java.lang.Thread class and provide an implementation for the run() method by overriding it.
1
2
3
4
5
6
7
8
package com.fork52.threading;

public class SampleThread extends Thread {
	@Override
	public void run() {
		System.out.println("Performing operation...");
	}
}
1
2
3
4
5
6
7
8
9
package com.fork52.threading;
// Usage

public class ThreadingMain {
	public static void main(String args[]) {
		SampleThread sampleThread = new SampleThread();
		sampleThread.run();
	}
}
  • By default, the Thread class provides an empty run method implementation as default implementation. The run() method is where you need to provide your code which needs to be run as a thread.

  • However, this is not a recommended approach to create Threads as the SampleThread class now cannot extend any other class if we wanted it to.

  • This is the recommended approach as its more flexible. We are not subclassing a concrete class to add threading functionality. We are implementing the run() method of java.lang.Runnable interface.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package com.fork52.threading;

public class SampleThreadRunnable implements Runnable {

	@Override
	public void run() {
		System.out.println("Performing operation...");
	}
	
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package com.fork52.threading;
// Usage

public class ThreadingMain {
	public static void main(String args[]) {
		SampleThreadRunnable sampleThreadRunnable = new SampleThreadRunnable();
		Thread thread = new Thread(sampleThreadRunnable);
		thread.start();
	}
}
  • Notice how we are passing the Runnable object into the Thread class object.

  • Also, we are now invoking start() method instead of run().

  • Since Runnable interface is a Functional interface, we can use lambdas to pass our thread code which makes our code concise and makes you look cool ๐Ÿ˜Ž.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package com.fork52.threading;

public class ThreadingMain {
	
	public static void main(String args[]) {
		Thread thread = new Thread(() -> System.out.println("Performing some operation.."));
		thread.start();
	}
	
}
Note
  • Thread.sleep(long millis) can be used to pause a thread. It throws InterruptedException, hence the exception needs to be handled using a try-catch block.
  • The join method allows one thread to wait for the completion of another.
  • If t is a Thread object whose thread is currently executing, t.join(); causes the current(parent) thread to pause execution until t's thread terminates.
  • This is helpful when one thread is dependent on another threadโ€™s completion. We can make the dependent thread wait for its dependencies to execute first.

In the upcoming posts, I will try to cover concurency and synchronization. Have a nice day! ๐Ÿ˜‡
  1. Oracle Java 8 docs