By Md. Sabuj Sarker | 9/25/2017 | General |Beginners

Programming With Threads in Java

Programming With Threads in Java

Java provides language level support for programming with threads. Without thinking about on which host operating system your Java application is running, you can code your multithreaded application. Unlike some other languages, Java prefers threads over processes. It provides an object oriented way of handling threads instead of working with some OS level thread primitives. Java made programmers free from the hassle of locking and unlocking some mutex to work on some non-thread safe code section and has provided us with the synchronized keyword to place on methods and on code blocks. As being a modern and flexible language, Java provides other mechanisms too.

What is a Thread

What is a thread? A thread can be defined in various ways and no single definition satisfies every programmer or every need. I am not going to provide some bookish definition here. Instead I am putting it the following way. Think that an application is a container. So, a container can only be a host for other things. Something inside it is actually run or executed. Your code gets compiled to bytecodes and JVM transforms that into machine code. The thing that runs or executes the machine code is called the thread. Now, let's just assume that your code runs—forgetting that it goes through other phases before it really can run or get executed. An application can have more than one cooperating processes. Java's concurrency model is based on threads and thus a Java applications usually contains only one process. We often say that a process runs or executes. But technically that is not true. In reality a thread runs. Every process must have at least one thread inside of it. We call the primary thread the main thread. When the main thread exists, the process exits. Main threads can create other threads.

Process vs Thread

As I’ve already mentioned a process do not run—a thread runs. A process is actually a container for threads and every process can contain one or more thread. Processes are heavyweight but threads are lightweight. A process needs a separate private area of main memory or RAM that is virtual memory for that process. On the other hand a thread does not need any separate private area of memory. It only needs a private runtime stack. Creating process is costly compared to creating threads. Communication between processes needs more time and resources but communication between threads is faster and easier. Processes cannot share objects directly but threads can. For all those reasons along with some other benefits, threading is always the preferred mechanism of concurrency in Java.

Getting Started

To get started with multithreaded programming in Java you need nothing special. Like other ordinary Java application development you need to have JDK installed in your system. You can choose any code editor or IDE you like. You can choose to compile the code with the help of an IDE or directly from the command line interface using the javac compiler. Create a project and create a public class with a main method inside of it with the name 'JavaThreading' or anything else you like. Our initial code should look like the following.

public class JavaThreading {
   public static void main(String[] args){
       // Our code goes here
   }
}

 

Creating And Running A Thread

To create a thread you need to instantiate the Thread class and call its start() method. So, our code looks like the following.

public class JavaThreading {
   public static void main(String[] args){
       Thread th = new Thread();
       th.start();
   }
}

Hit build and run. But our program does nothing. We haven't told it to do anything yet. We did not tell it which code it should run.

Create another class called MyThread1 that extends Thread. Override the run() method inside of it.

public class MyThread1 {
   public void run(){
       System.out.println("From MyThread1: Hi, I am getting printed from MyThread1");
   }
}


Now inside the public class:

public class JavaThreading {
   public static void main(String[] args){
       Thread th = new MyThread1();
       th.start();
   }
}


Hit build and run to see the following result.

From MyThread1: Hi, I am getting printed from MyThread1

Running Multiple Threads

In the previous section we had only one extra thread running (the other being the main thread). But we need to start multiple tasks at the same time. So, create another class called MyThread2.

public class MyThread2 extends Thread{
   public void run(){
       System.out.println("From MyThread2: Hi, I am getting printed from MyThread2");
   }
}

And inside the public class:

public class JavaThreading {
   public static void main(String[] args){
       System.out.println("From the main thread: Going to create and start the threads");
       Thread th1 = new MyThread1();
       Thread th2 = new MyThread2();
       th1.start();
       th2.start();
       System.out.println("From the main thread: created and started other threads");
   }
}


Hit build and run to see an output similar to the following:

From the main thread: Going to create and start the threads
From the main thread: created and started other threads
From MyThread1: Hi, I am getting printed from MyThread1
From MyThread2: Hi, I am getting printed from MyThread2


You may not see the output in the same order always. There is no guarantee that the threads will run the same way as you created or started them.

To demonstrate the result more clearly, let's modify our class in the following manner.

MyThread1

public class MyThread1 extends Thread{
   public void run(){
       for(int i = 0; i < 10; i++){
           System.out.println("From MyThread1: print with index: " + i);
       }
   }
}



MyThread2

public class MyThread2 extends Thread{
   public void run(){
       for(int i = 0; i < 10; i++){
           System.out.println("From MyThread2: print with index: " + i);
       }
   }
}



Change the public class in the following way with the join method on the thread, so that the main thread does not exit before the other threads finish their work.

public class JavaThreading {
   public static void main(String[] args) throws Exception{
       System.out.println("From the main thread: Going to create and start the threads");
       Thread th1 = new MyThread1();
       Thread th2 = new MyThread2();
       th1.start();
       th2.start();
       System.out.println("From the main thread: created and started other threads");

       th1.join();
       th2.join();
   }
}



Hit build and run again. My result looks similar to the following.

From the main thread: Going to create and start the threads
From the main thread: created and started other threads
From MyThread1: print with index: 0
From MyThread1: print with index: 1
From MyThread1: print with index: 2
From MyThread1: print with index: 3
From MyThread1: print with index: 4
From MyThread1: print with index: 5
From MyThread1: print with index: 6
From MyThread1: print with index: 7
From MyThread1: print with index: 8
From MyThread1: print with index: 9
From MyThread2: print with index: 0
From MyThread2: print with index: 1
From MyThread2: print with index: 2
From MyThread2: print with index: 3
From MyThread2: print with index: 4
From MyThread2: print with index: 5
From MyThread2: print with index: 6
From MyThread2: print with index: 7
From MyThread2: print with index: 8
From MyThread2: print with index: 9

The result still looks sequential. It is a small task and each thread has enough opportunity or time before the OS switched them. Let's put each thread to sleep after printing the data. To put a thread to sleep use the Thread.sleep() method inside threads.

MyThread1

public class MyThread1 extends Thread{
   public void run(){
       for(int i = 0; i < 10; i++){
           System.out.println("From MyThread1: print with index: " + i);
           try {
               Thread.sleep(100);
           }catch(Exception ex){
               ex.printStackTrace();
           }
       }
   }
}


MyThread2

public class MyThread2 extends Thread{
   public void run(){
       for(int i = 0; i < 10; i++){
           System.out.println("From MyThread2: print with index: " + i);
           try {
               Thread.sleep(100);
           }catch(Exception ex){
               ex.printStackTrace();
           }
       }
   }
}


Hit build and run to see results similar to the following.

From the main thread: Going to create and start the threads
From the main thread: created and started other threads
From MyThread1: print with index: 0
From MyThread2: print with index: 0
From MyThread1: print with index: 1
From MyThread2: print with index: 1
From MyThread1: print with index: 2
From MyThread2: print with index: 2
From MyThread2: print with index: 3
From MyThread1: print with index: 3
From MyThread2: print with index: 4
From MyThread1: print with index: 4
From MyThread1: print with index: 5
From MyThread2: print with index: 5
From MyThread1: print with index: 6
From MyThread2: print with index: 6
From MyThread2: print with index: 7
From MyThread1: print with index: 7
From MyThread2: print with index: 8
From MyThread1: print with index: 8
From MyThread1: print with index: 9
From MyThread2: print with index: 9

Look, this time the output is coming from both threads. So, our threads are running concurrently.

Runnable Or Subclass Of Thread

The object that we put inside the Thread's constructor to start a thread can be a subclass of thread or an implementation of a Runnable interface. It is your personal choice which way you go. But my recommendation is you implement the Runnable interface, because it will give you a lot of flexibility when you go further in multithreaded application with Java. Implementing a Runnable interface, your code might look like the following.

public class MyThread1 implements Runnable{
   public void run(){
       for(int i = 0; i < 10; i++){
           System.out.println("From MyThread1: print with index: " + i);
           try {
               Thread.sleep(100);
           }catch(Exception ex){
               ex.printStackTrace();
           }
       }
   }
}

 

Conclusion

Java provides extensive support for threading. In this article I have covered various basic aspects of threading but only the most basic way of threading. In future articles I will discuss more advanced techniques.

 

More Java? Check out Processing ZIP Files with Java.

 

Be sure to stop by the homepage to search and compare SDKs, Dev Tools, and Libraries.

By Md. Sabuj Sarker | 9/25/2017 | General

{{CommentsModel.TotalCount}} Comments

Your Comment

{{CommentsModel.Message}}

Recent Stories

Top DiscoverSDK Experts

User photo
3355
Ashton Torrence
Web and Windows developer
GUI | Web and 11 more
View Profile
User photo
3220
Mendy Bennett
Experienced with Ad network & Ad servers.
Mobile | Ad Networks and 1 more
View Profile
User photo
3060
Karen Fitzgerald
7 years in Cross-Platform development.
Mobile | Cross Platform Frameworks
View Profile
Show All
X

Compare Products

Select up to three two products to compare by clicking on the compare icon () of each product.

{{compareToolModel.Error}}

Now comparing:

{{product.ProductName | createSubstring:25}} X
Compare Now