Multithreading in Java

612


Java has build in support for multithreading. In short multithreading is running two or more parts of your program in parallel.

Creating Threads

In Java you can create threads in two ways

  1. By extending Thread Class
  2. By implementing Runnable Interface (Recommended way)

Lets see examples for these two ways.

By extending Thread Class


public class ThreadsHelloWorld {
	public static void main(String[] args) {

		ThreadExample thred = new ThreadExample();
		thred.start();
		System.out.println("You should see this message first in console");

	}
}

class ThreadExample extends Thread {
	public void run() {
		try {
			Thread.sleep(1_000);
		} catch (InterruptedException e) { /* Ignore*/ }
		
		System.out.println("This runs after a second");
	}
}

By implementing Runnable Interface (Recommended way)


public class ThreadsRunnableHelloWorld {
	public static void main(String[] args) {

		Thread thred = new Thread(new ThreadExampleRunnable());
		thred.start();
		System.out.println("You should see this message first in console");

	}
}

class ThreadExampleRunnable implements Runnable {
	public void run() {
		try {
			Thread.sleep(1_000);
		} catch (InterruptedException e) { /* Ignore*/ }
		
		System.out.println("This runs after a second");
	}
}

Following code is a short version of above code by making the Runnable as anonymous inner-class, so that you don't have to create a separate Class which implements Runnable Interface.

public class ThreadsRunnableHelloWorld {
	public static void main(String[] args) {

		Thread thred = new Thread(new Runnable() {

			@Override
			public void run() {
				try {
					Thread.sleep(1_000);
				} catch (InterruptedException e) {/* Ignore */ }

				System.out.println("This runs after a second");
			}
		});
		
		thred.start();
		System.out.println("You should see this message first in console");

	}
}

Thread Pools

There are two major advantages of having Thread Pools rather creating your own Threads on demand

  1. We can limit the number of threads running in your application in parallel. You can decide the number of threads that can run in parallel by looking at your System capabilities.
  2. You can avoid the Thread creation overhead.

Java has java.util.concurrent.Executors using which you can create Thread Pools.
Java has different flavours of thread pools, based on your use-case you can pick one of them. Following are the most commonly used Thread Pools

  1. CachedThreadPool
  2. FixedThreadPool
  3. SingleThreadExecutor
  4. ScheduledThreadPool

Following example shows you how to create these thread pools and how to submit tasks to those thread pools.

import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ThreadPools {
	public static void main(String[] args) throws InterruptedException {
		
		// useful when you have many short lived tasks 
		ExecutorService cachedThreadpool = Executors.newCachedThreadPool();
		
		// creates given fixed number of threads, they will be live even though there is no work
		ExecutorService fixedThreadpool = Executors.newFixedThreadPool(10);
		
		// creates executer with one thread, all the runnables submitted will get executed one after another 
		ExecutorService singleThreadpool = Executors.newSingleThreadExecutor();
		
		// used to run a task periodically
		ScheduledExecutorService scheduledThreadpool = Executors.newScheduledThreadPool(10);
		
		Runnable someTask = new Runnable() {
			@Override
			public void run() {
				System.out.println("Hello World from a pool. Executing Thread:" 
						+ Thread.currentThread().getName() + " Time:" + new Date());
				
			}
		};
		
		cachedThreadpool.submit(someTask);
		fixedThreadpool.submit(someTask);
		singleThreadpool.submit(someTask);
		
		// Schedules the task once after 2000 milliseconds
		scheduledThreadpool.schedule(someTask, 2_000, TimeUnit.MILLISECONDS); 
		
		// Schedules a task periodically every 2000 milliseconds, after an initial delay of 1000 milliseconds
		scheduledThreadpool.scheduleAtFixedRate(someTask, 1_000, 2_000, TimeUnit.MILLISECONDS); 
		
		
		Thread.sleep(10_000);
		
		cachedThreadpool.shutdown();
		fixedThreadpool.shutdown();
		singleThreadpool.shutdown();
		scheduledThreadpool.shutdown();
		
		System.out.println("Shutdown all the pools");
	}
}

Output

Hello World from a pool. Executing Thread:pool-1-thread-1 Time:Sun Sep 10 14:35:32 IST 2017
Hello World from a pool. Executing Thread:pool-2-thread-1 Time:Sun Sep 10 14:35:32 IST 2017
Hello World from a pool. Executing Thread:pool-3-thread-1 Time:Sun Sep 10 14:35:32 IST 2017
Hello World from a pool. Executing Thread:pool-4-thread-1 Time:Sun Sep 10 14:35:33 IST 2017
Hello World from a pool. Executing Thread:pool-4-thread-2 Time:Sun Sep 10 14:35:34 IST 2017
Hello World from a pool. Executing Thread:pool-4-thread-1 Time:Sun Sep 10 14:35:35 IST 2017
Hello World from a pool. Executing Thread:pool-4-thread-3 Time:Sun Sep 10 14:35:37 IST 2017
Hello World from a pool. Executing Thread:pool-4-thread-2 Time:Sun Sep 10 14:35:39 IST 2017
Hello World from a pool. Executing Thread:pool-4-thread-1 Time:Sun Sep 10 14:35:41 IST 2017
Shutdown all the pools