Java Multithreading Tutorial: Thread Class, Runnable, and Methods
What is Multithreading?
Multithreading is a part of a process that has the ability to perform more than one job concurrently.
The main method is the main thread in Java, where your program execution starts. But the main thread executes tasks one by one. If you want to execute multiple tasks at the same time, you need to create multiple threads from your main method.
Using multithreading, you can achieve multitasking.
There are two ways to achieve multitasking:
- Multiprocessor based
- Multithread based
Both are part of the operating system. So you can request a thread be created through the thread scheduler of the OS.
Java supports multithreading but not multiprocessing for these reasons:
| Process | Thread |
|---|---|
| Process is a group of threads. | Thread is part of a process or a sub-process. |
| Process is heavyweight. | Thread is lightweight. |
| Process has its own memory area. | Thread shares the process memory. |
| Inter-process communication is very expensive. | Inter-thread communication is cheap. |
| Process affects the main memory. | Thread affects the process memory. |
Note: In Java, a process is provided by default. You do not need to worry about the process. You just create a thread and perform your task.
Thread Scheduler
The thread scheduler is responsible for maintaining the sequence of thread execution — deciding which thread should be given preference over others.
The scheduling depends on the algorithm of the scheduler, such as preemptive scheduling and time slicing with round robin.
Preemptive scheduling: The highest-priority task executes until it enters the waiting or dead state, or a higher-priority task comes into existence.
Time slicing: A task executes for a predefined slice of time and then re-enters the pool of ready tasks.
Why Multithreading?
- Multithreading uses the full CPU power.
- You can execute multiple tasks at the same time.
- You save execution time.
- You reduce response time.
- You can serve multiple clients at the same time.
When to use Multithreading?
Multithreading is used when you have limited resources.
Example: A single shopping website can be accessed by multiple clients at the same time. That shopping site is a single resource (a limited resource).
What is a Thread?
- A thread is a lightweight sub-process.
- Every thread has its own stack where you define separate thread tasks.
- You can create your own threads to perform multiple tasks at the same time.
There are two ways to create a thread:
- By extending the Thread class
- By implementing the Runnable interface
1. By extending Thread class
The Thread class is a predefined class in Java that exists in the java.lang package.
Use the Thread class when you want to use only thread resources, because in this case you cannot extend any other class.
The Thread class also implements the Runnable interface.
You need to override the run() method to define a task, and call the start() method to create a thread through the thread scheduler.
The Thread class provides the following methods:
| Return type | Method with description |
|---|---|
| Thread | Thread.currentThread() — returns the currently running thread object. |
| long | getId() — returns the identifier of this thread. |
| String | getName() — returns the name of this thread. |
| int | getPriority() — returns the priority of this thread, between 1 and 10. |
| Thread.State | getState() — returns the state of this thread: NEW, RUNNABLE, BLOCKED, WAITING, TERMINATED, and so on. |
| ThreadGroup | getThreadGroup() — returns the ThreadGroup object of this thread. |
| boolean | isAlive() — returns whether the thread is alive or terminated. |
| boolean | isDaemon() — checks whether this thread is a daemon (service) thread. |
| boolean | isInterrupted() — tests whether this thread has been interrupted. |
| void | join() — waits for this thread to die (terminate). |
| void | run() — defines the task executed by this thread. |
| void | setDaemon(boolean on) — marks this thread as a daemon or user thread. |
| void | setName(String name) — sets the name of this thread. |
| void | setPriority(int priority) — sets the priority between 1 and 10, or use constants like MAX_PRIORITY, MIN_PRIORITY, and NORM_PRIORITY. |
| void | start() — begins execution. The JVM calls the run() method of this thread. |
| void | Thread.sleep(long milliseconds) — causes the currently executing thread to sleep for the specified number of milliseconds. |
| void | Thread.yield() — a hint to the scheduler that the current thread is willing to yield its use of a processor. |
Thread Examples
Hello World program
public class Test extends Thread {
@Override
public void run() {
System.out.println("Hello World");
}
public static void main(String[] args) {
new Test().start();
}
}
Result: Hello World
How to get the current thread
public class Test {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());
}
}
Result: main
How to check whether a thread is created
public class Test extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
new Test().start();
}
}
Result: Thread-0
If you do not call start()
public class Test extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
new Test().run();
}
}
Result: main
Note: If you call the run() method directly, no new thread is created. The task executes on the main thread.
If you call start() twice
public class Test extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
Test t = new Test();
t.start();
t.start();
}
}
Result: Thread-0
IllegalThreadStateException
Note: If you call start() twice on the same object, you get an IllegalThreadStateException.
How to create multiple threads
public class Test extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
Test t1 = new Test();
t1.start();
Test t2 = new Test();
t2.start();
}
}
Result: Thread-0
Thread-1
2. By implementing Runnable interface
The Runnable interface is a predefined interface in Java that exists in the java.lang package.
Runnable has only one method: run().
Use the Runnable interface when you need to extend another class and also use thread resources.
You implement the Runnable interface in your class and override the run() method to define the task.
How to create a thread using Runnable
public class Test implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
Test t = new Test();
// Here the implementing class is called the runnable target.
// The runnable target is associated with a Thread object.
Thread tt = new Thread(t);
tt.start();
}
}
Result: Thread-0
How to create multiple threads with Runnable
public class Test implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
Test t = new Test();
Thread tt0 = new Thread(t);
tt0.start();
Thread tt1 = new Thread(t);
tt1.start();
}
}
Result: Thread-0
Thread-1
Note: You can use either way to create a thread, based on your requirements.
Where to go next
You now know what a thread is, how the scheduler decides which one runs, how to create threads with both the Thread class and Runnable, and the methods you will use most often.
If you remember one thing, remember this: calling start() creates a new thread. Calling run() does not. That one difference is the entire point of multithreading.
If you want to go deeper, try these next steps:
- Add
Thread.sleep(1000)insiderun()and watch the output order change. - Set different priorities on two threads and observe how the scheduler behaves.
- Use
join()to make the main thread wait for a worker thread to finish. - Move on to synchronization. The moment two threads share a variable, you need to understand race conditions and the
synchronizedkeyword.
No comments:
Post a Comment