Java Multithreading

byTrevor PageonJanuary 4, 2013

Today I want to introduce the topic of Java multithreading to you. This is a bit of an advanced topic, so if you are not familiar with Java programming, I would recommend starting with the basics. If you have been around the Java programming block and have not yet tried your hand at multithreading, then that’s great! Let’s get started.

What is Java Multithreading?

In Java, a Thread is essentially the Object that represents one piece of work. When you start your application and it starts to run, Java has “spawned” (created) a Thread and this Thread is what will carry out the work that your application is meant to do. What’s interesting to note, is that one Thread can only do one particular task at a time. So that would mean it’s a bit of a bottleneck if your entire application just works off of one Thread right? Right!

Java multithreading allows you to do multiple tasks at the same time. This is possible because modern day computers have multiple CPUs (CPUs are the brain of your computer, and it has a bunch!). One CPU can work on one Thread at a time (unless your CPUs have hyper-threading, in which case it can handle two at a time). So this means that if your computer has 4 CPUs with hyper-threading technologies, your code could potentially handle 8 Threads at the same time. Neat!

The implications of this are that you can take your code and make it perform MUCH better by introducing the use of multithreading. That is of course, if your program would benefit from the use of multithreading, some applications are fairly simple and things would just get over-complicated by adding in Thread logic.

How do we use it in Java?

Well, it’s really not too tough to implement the use of Threads in Java. The trick is ensuring that all the Threads cooperate properly with each other… but I’ll get into that after I show you an example of how to set yourself up with Threads.

All you need to do to use Threads is to have an Object implement the Runnable interface and override the run method. Here’s an example of a Class named Worker.

This is currently running on the main thread, the id is: 1
This is currently running on a separate thread, the id is: 9

So you can see here that there are two different Threads running here. Now in this example, there’s really no need to be using two different Threads because the flow of this code is linear. The trick here would be to introduce the need for multiple Workers to be running at the same time, and to have a lot of work for these Workers to carry out. We can easily create lots of Workers, I’ll just use a for loop to create a handful. But how could we simulate lots of work? Well, we could use the Thread.sleep() method; this method pauses the thread for a custom defined period of time. When we pause a Thread, this would simulate that Thread being busy doing some sort of actual work! Sweet, so let’s see what that would look like:

So what's the output of the code above? Here's what it says on my computer:

This is currently running on the main thread, the id is: 1
This is currently running on a separate thread, the id is: 9
This is currently running on a separate thread, the id is: 10
This is currently running on a separate thread, the id is: 11
This is currently running on a separate thread, the id is: 12
This is currently running on a separate thread, the id is: 13
This whole process took: 5 seconds.

Cool, so that's what I would expect to see. If you look at the code, each worker "sleeps" for 5 seconds, this simulates 5 seconds of work that they are doing. So since we are using multithreading, firing up 5 different workers to carry out 5 seconds of work each should take 5 seconds total. So what happens if we take out the concept of multithreading? How long would this process take? We it would have to create each Worker one at a time and have each one carry out their work in a linear fashion, so it would take 25 seconds to complete. So technically, by implementing multithreading here, we have increased the speed of our processes by 500%! Not too shabby.

Want Free Access to my Best Java Courses?

Alright, so if you're read this far down the article, then you're clearly interested in learning how to code. You can currently get access to my 2 best courses on Java for free for 30 days (then it's just $10/month afterwards, or $97/year).

When you sign up you'll receive login information to start learning about Java. If you decide you don't like the courses, you can cancel at any time. If you decide you love the courses then you don't have to do anything and you can stay subscribed for as long as you like for just $10/month or $97/year.

It's like Netflix for coders!

Go ahead an click the button below to get started!

Pitfalls of Java Multithreading

One thing I didn't touch on in this article is what's known as Synchronization, and this is the bane of the multithreading programmer's existence. This is because when you introduce the concept of multithreading, you are opening up the possibility of two Threads accessing/modifying the same Object in memory at the same time. When you try to do this, Java will throw an Exception. The solution to this problem is to synchronize access to your Objects so that no two Threads can trample over each other when trying to access any Object's properties/resources.

Another problem that arises with the use of Java multithreading is race conditions. This is when your code's output is based on a particular sequence of events, but with multithreading this is not a great idea, because you can't always guarantee that a particular set of events will happen in any particular order. Here's a wiki article explaining this problem: http://en.wikipedia.org/wiki/Race_condition.

I won't be touching on these concepts just yet, as I have already covered a lot for you to take in. The knowledge in this Java tutorial will be critical in completing the next Java practice assignment, so if you intend on completing it, be sure to understand what I'm explaining in this entire article.

Good post . I really like your assignment post , good work there. Importance of multi-threading is huge in Java space and correct understanding of threading concept is very important for any Java developer. Skill to find and avoid concurrency issues like thread-safety, deadlock and race conditions are getting increasingly important with programming on multi core processors. Cheers.

Very good post, Trevor.
One of my main problems in Java is understanding Exceptions.
So I searched for InterruptedException and found this article: http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html
It states: “never swallow InterruptedException”, which your e.printStackTrace() does… (which never occured in my several test runs). What is your opinion?

Second: when running your second example, I *sometimes* get “The whole process took: 0 seconds.” followed by the 5 id messages.

It’s true that you shouldn’t make a habit of “swallowing” exceptions. At the very least you should have an e.printStackTrace() so that you can see an error if it does occur (the exception stack trace will be printed to the console). If I were to be more thorough, I would likely output this message to a log and perhaps display it to the user, though usually displaying exceptions to the user is not the best choice. In the case of this example, I felt it wasn’t necessary to handle this exception.

To answer your second question, that is very odd… the only explanation I could come up with is that the Thread.sleep() code failed to work, were their exceptions in your console when it took 0 seconds?

1) the article states, you have to rethrow the InterruptedException, otherwise that Thread could possibly never end.

2) There were no exceptions at all, the main() thread always ends normally after 5 seconds (header line of the console window).
I’m using Java 1.6 and leave STS open all the time.
If I change the source code (add comments, etc.), the first run is always OK, but the the next runs will only be OK if I wait several minutes before the next run, otherwise the described behaviour occurs with main() ending after 5 seconds, too.
Java bug? Garbage collector?

1) Nice, I’ve updated the source code to reflect these findings, thanks for pointing that out (I learn something new everyday).

2) It would be rare if it were a Java bug… I’m a bit stumped as to why this would happen.. I was thinking it could be something to do with synchronization (as that’s where most bugs in multithreading come from). I’m not able to reproduce the problem you’re talking about on my PC (I also keep STS open for days on end).

Just to be sure that I have not created a source error, I created a new class WorkerOrig, copied your source into it from above, replaced all “Worker” by “WorkerOrig”.
The result is absolutely random OK or BAD, has nothing to do with waiting time between runs or modifying/saving the source or restarting STS.

BAD result ( occuring after 5 seconds, no exception visible):
WorkerOrig[Java Application] …
This is currently running on the main thread, the id is: 1
This whole process took: 0 seconds.
This is currently running on a separate thread, the id is: 9
This is currently running on a separate thread, the id is: 11
This is currently running on a separate thread, the id is: 8
This is currently running on a separate thread, the id is: 10
This is currently running on a separate thread, the id is: 12

OK, as expected:
WorkerOrig[Java Application] …
This is currently running on the main thread, the id is: 1
This is currently running on a separate thread, the id is: 8
This is currently running on a separate thread, the id is: 9
This is currently running on a separate thread, the id is: 10
This is currently running on a separate thread, the id is: 12
This is currently running on a separate thread, the id is: 11
This whole process took: 5 seconds.

I literally just ran into that case with Assignment 3 that I’m working on right now. I’m ironing out all the bugs in the unit tests that I’m writing for everyone, and this exact scenario was the culprit. Multithreading is very tricky and forces one to think outside the box!

I quite a novice at this and I have a question. In the code, we are saying, we would sleep on the main thread for 100 milliseconds for EACH of the 5 worker objects.

// We must force the main thread to wait for all the workers
// to finish their work before we check to see how long it
// took to complete
for (Worker worker : workers)
{
while (worker.running)
{
Thread.sleep(100);
}
}

The worker threads sleep for 1 second EACH.

Does that not mean that in total, the process should take 5 seconds and 500 milliseconds?
I don’t understand why the “This whole process took: 5 seconds.”

Why is it necessary for the main thread to wait until the worker thread completes it work and why must it wait 100 milliseconds?

The trick here is to understand that there are 6 threads running simultaneously.

Thread 1 = Main thread
Threads 2-6 = Workers

So what will happen is the main thread (Thread 1) creates 5 new threads (Threads 2-6). The main thread (Thread 1) then waits any reasonable “unit of time” (In this case I chose 100 milliseconds, but I could have chosen 1 millisecond, or 10, or 25, or 50 etc. so long as it’s divisible by 5000) until the workers are done, then thread 1 reports its findings on how long the whole process took.

So if we were to lay it out on a timeline with the code I wrote, it may look something like this:

0 milliseconds -> Start main thread and start all worker threads
100 milliseconds -> main thread done sleeping, check if workers are done (they are not, it hasn’t been 5sec)
200 milliseconds -> main thread done sleeping, check if workers are done (they are not, it hasn’t been 5sec)
300 milliseconds -> main thread done sleeping, check if workers are done (they are not, it hasn’t been 5sec)
400 milliseconds -> main thread done sleeping, check if workers are done (they are not, it hasn’t been 5sec)
500 milliseconds -> main thread done sleeping, check if workers are done (they are not, it hasn’t been 5sec)
…
5000 milliseconds -> main thread done sleeping, check if workers are done (they ARE done working, as it’s been 5 seconds)
-> calculate how long it has taken to complete this process and report findings to console

I am still confused with your statement “each worker ‘sleeps’ for 5 seconds, this simulates 5 seconds of work that they are doing”. How can we say that sleep simulating 5 second of work? What I understand is calling “Thread.sleep()” will interrupt another thread to run, while doing a real work should not call another thread because otherwise the current thread will not process the work completely. Please correct me if I am wrong.

Invoking the Thread.sleep() method will not actually interrupt another thread to run, it will simply force the current Thread to pause and wait for the duration that you’ve specified. The reason why I used the sleep method as a “simulation of work” is because if I were to put actual “work” (like a bunch of calculations and loops or soemthing) into the mix, each computer would process that work differently and the results would vary for everyone.

I hope that helps clear things up, let me know if you still have questions though!

After understanding the basics of Java multithreading, I recommend to check the Executors framework. Together with various built in classes, making complex multithreaded applications is simpler and cleaner than using Threads directly.

There are a ton of articles about the topic, you can check a practical one I wrote where I show how easy can be to write synchronization that could be complex by using simple locking:

hallo Trevor
I would like to know, how can I make the I.D of second thread to start from 8?, like
This is currently running on the main thread, the id is: 1
This is currently running on a separate thread, the id is: 5
This is currently running on a separate thread, the id is: 6
This is currently running on a separate thread, the id is: 7
This is currently running on a separate thread, the id is: 8
This is currently running on a separate thread, the id is: 9
This whole process took: 5 seconds.

A thread is a single sequential flow of control within a program. A thread is similar to the sequential programs described previously. A single thread also has a beginning, a sequence, and an end. Many thanks for sharing this tutorial.