Beginners Programs :

Multithreading In Java – Tutorial & Examples | JavaTutorials

Multithreading in Java,  is the mechanism of executing different parts of a program simultaneously.

Suppose, in a normal program, we are in one method and calling another method then the control goes to the called method, executes the statements in that method and comes back to calling the method.

As long as the control executes the method, the statements after the method call are not executed in the calling method. Those statements are executed only after the control comes back from called method.

Example: 

In the above example, when method two() is called from method one(), then the control goes to the definition of two() and executes ‘Somecode’. As long as that code is executed the one() will wait.

Once the execution of two() is complete, the control comes back to one() to execute ‘Somestatements’. This is what happens in a normal (single-threaded) program.

If we want to execute both the parts (‘Somecode’ and ‘Somestatements’) at a time (in parallel) then we should approach multi threading.

Java Multi Threading Example & Suitable Examples

  • The ‘multithreading’ can be seen at many places in our computers.
  • Suppose we are playing a game and at the same time listening to some music.
  • In that case both the applications (processes) are placed in the process queue and the processor will work on them in a time sharing manner.
  • For a normal user, it looks like both the things (game and music) are running simultaneously.
  • In fact, the processor works on each process one after another (spending very small amounts of time on each) where the small time cannot be identified by us.

Suppose the processor started working on a song (some music) and spent 1 millisecond (supposed time). In that one millisecond, the processor takes data from the song file and gives to the audio device.

The data gathered by the processor in 1 millisecond will be played by 1 minute (suppose). In the meanwhile (next millisecond), the processor will work on other processes (say game) and works on it.

  • Maybe the processor will work on the game for 1 millisecond. In that 1 millisecond, the processor will take user inputs (through the keyboard, mouse, joystick, etc) and performs the required operation.
  • Again in the third millisecond, the processor will work on the song. This way the processor keeps working on both parallelly.
  • If we have more processes then the processor will work on all those processes simultaneously (from a user point of view) and one by one in a cycle (inside). All of this mechanism is known as process-based multi-tasking.

Similar to this, we can divide our program into different processes (threads) and execute all the threads simultaneously. It means it looks like simultaneous to a normal user but the system will keep working on them on a time-sliced basis.

At one time the system works on one process/part/thread only and that small amount of time is generally not recognized by the user. This mechanism is known as thread based multitasking.

Process-based multitasking is controlled by operating system and thread based multi-tasking can be controlled by our program. This thread based multi-tasking is also known as Multithreading.

Suppose we are writing a program for a car race and multiple cars should be running simultaneously (in parallel).

  • Let us assume each car is an object.
  • If we write the program in a single thread, we can move only one car at one time.
  • When a car is moving other cars should stand unmoved.
  • This is not acceptable to be a race.
  • We should see all the cars moving in parallel.

To get this effect, we should approach multi-threading where each car is moved by one thread and all the threads will run in parallel irrespective of other threads.

In Java, the class Thread helps to achieve multi threading. When we want to provide multi threading features to a class, then we can inherit Thread class to that class.

Example: 

When we create an object of the above class Alpha, that object will have Thread facilities. Once such an object is started ( using the method start() ) the control creates a separate branch and executes the code in the Alpha class.

Example:

The start method creates a new branch and starts run() method automatically. We should define the run() method in the corresponding class (Alpha, in our example).

Example:

Suppose, in the following program we have created an object of class Alpha and started it. When the thread has started the run() method of the class Alpha is executed in a separate branch and at the same time, the remaining code in main() method is executed.

The code in run() prints alphabets (A B C D ….. Y Z) and the code in main() prints numbers (1 2 3 ……. 24 25). As both the codes execute simultaneously we can see both outputs printed together (mixed).

Example:         

Output (probable):

The output may vary from one execution to another execution as the amount of time spent by the system on each thread may vary from time to time. This time depends on the number of processes running currently, RAM capacity, processor speed, etc.

In the above example, a is referring to a thread object and we can create any number of such objects.  Is When we create a thread object but not yet started, then we say that the thread is in the READY state. Once the thread starts we call that the thread is in RUNNING state.

  • Sometimes a thread should wait (suspend its operations temporarily) up to some other thread completes some task.
  • Such a period is known as WAITING state.
  • The WAITING state is part of the RUNNING state.

When a thread completes its execution (completes the corresponding run() method), we say that the thread is in DEAD state.

Methods In Thread Operations

  • isAlive() to know whether a thread is in running state or not. It checks whether the invoking thread is running/active/alive. If so, It returns true otherwise it returns false.
  • wait(): It makes a thread wait till same other thread completes its work and notify it. If no other thread notifies then the waiting state only indefinitely.
  • wait(long milliseconds): This method waits for a maximum of the specified number of milliseconds for a notification from other threads. If no notification comes within the time then the waiting thread automatically resumes.
  • wait(Milli, Nanos): This is similar to the previous method wait(long milliseconds) but it can take nanoseconds also as waiting time.
  • join(): join() to make a thread wait until some other thread completes its execution.

It is a method that makes the parent thread wait until another thread completes its execution and joins the current thread.

In the following example, the thread in which method( ) is executed is the current thread from the current thread another thread (branch) is started so the code of the branch (another thread) and statement 1 and statement 2 of the current thread are executed in parallel.

Statement 3 and statement 4 of current thread are executed only after the branch thread completes the execution.

Example:

Example using setPriority():

Output: (It may vary for different compilers)

Output:

Example Program: