Java provides built-in support for multithreaded programming. A multithreaded program consists of two or more parts that can run concurrently. Each part of the program is called a thread, and each thread defines a separate execution path.
Multithreading is a special form of multitasking, but it uses less resource overhead.
Another thread-related term is defined here – process: a process consists of memory allocated by the operating system and contains one or more threads. A thread cannot exist on its own; it must be part of a process. A process runs until all non-waiting threads have finished running.
Multithreading can satisfy programmers to write efficient programs to make full use of CPU.
The lifetime of a thread
Threads go through phases of their life cycle. The following figure shows the complete life cycle of a thread.
-
New state:
When a Thread object is created using the new keyword and the Thread class or its subclasses, the Thread object is created. It remains in this state until the program starts () thread.
-
Ready state:
When the thread object calls the start() method, the thread enters the ready state. A thread in a ready state is in a ready queue, waiting to be scheduled by the thread scheduler in the JVM.
-
Operating status:
If the ready thread acquires CPU resources, run() can be executed and the thread is running. The running thread is the most complex, and can be blocked, ready, or dead.
-
Blocking state:
If a thread executes methods such as sleep or suspend and loses occupied resources, the thread goes from running to blocked. You can re-enter the ready state when it is time to sleep or after obtaining device resources.
-
State of death:
When a running thread completes a task or other termination conditions occur, the thread switches to the terminated state.
Priority of the thread
Each Java thread has a priority, which helps the operating system determine the order in which threads are scheduled.
The priority of a Java Thread is an integer ranging from 1 (thread.min_priority) to 10 (thread.max_priority).
By default, each thread is assigned a priority of NORM_PRIORITY (5).
Threads with higher priority are more important to the program, and processor resources should be allocated before threads with lower priority. However, thread priority does not guarantee the order in which threads are executed and is very platform dependent.
Create a thread
Java provides two ways to create threads:
- By implementing the Runable interface;
- By inheriting the Thread class itself.
Threads are created by implementing the Runnable interface
The easiest way to create a thread is to create a class that implements the Runnable interface.
To implement Runnable, a class only needs to make a single method call to run(), declared as follows:
publicvoid run()
You can override this method, but it’s important to understand that run() can call other methods, use other classes, and declare variables, just like the main thread.
After creating a class that implements the Runnable interface, you can instantiate a thread object in the class.
Thread defines several constructors. The following is the one we often use:
Thread(Runnable threadOb,String threadName);
Here, threadOb is an instance of a class that implements the Runnable interface, and threadName specifies the name of the new thread.
It doesn’t run until you call its start() method after a new thread is created.
void start();
The instance
Here is an example of creating a thread and starting it to execute:
Class NewThread implements Runnable {Thread t; NewThread() {// Create a new Thread t = new Thread(this, "Demo Thread"); System.out.println("Child thread: " + t); t.start(); Public void run() {try {for(int I = 5; i > 0; i--) { System.out.println("Child Thread: " + i); // Suspend Thread thread.sleep (50); } } catch (InterruptedException e) { System.out.println("Child interrupted."); } System.out.println("Exiting child thread."); } } public class ThreadDemo { public static void main(String args[]) { new NewThread(); // create a new thread try {for(int I = 5; i > 0; i--) { System.out.println("Main Thread: " + i); Thread.sleep(100); } } catch (InterruptedException e) { System.out.println("Main thread interrupted."); } System.out.println("Main thread exiting."); }}Copy the code
The result of compiling the above program is as follows:
Child thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Main Thread: 4
Child Thread: 3
Child Thread: 2
Main Thread: 3
Child Thread: 1
Exiting child thread.
Main Thread: 2
Main Thread: 1
Main thread exiting.
Copy the code
Threads are created by inheriting threads
The second way to create a Thread is to create a new class that inherits the Thread class, and then create an instance of that class.
The inherited class must override the run() method, which is the entry point for the new thread. It must also call the start() method to execute.
The instance
Class NewThread extends Thread {NewThread() {// Create a second Thread super("Demo Thread"); System.out.println("Child thread: " + this); start(); Public void run() {try {for(int I = 5; i > 0; i--) { System.out.println("Child Thread: " + i); Thread.sleep(50); } } catch (InterruptedException e) { System.out.println("Child interrupted."); } System.out.println("Exiting child thread."); } } public class ExtendThread { public static void main(String args[]) { new NewThread(); // create a new thread try {for(int I = 5; i > 0; i--) { System.out.println("Main Thread: " + i); Thread.sleep(100); } } catch (InterruptedException e) { System.out.println("Main thread interrupted."); } System.out.println("Main thread exiting."); }}Copy the code
The result of compiling the above program is as follows:
Child thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Main Thread: 4
Child Thread: 3
Child Thread: 2
Main Thread: 3
Child Thread: 1
Exiting child thread.
Main Thread: 2
Main Thread: 1
Main thread exiting.
Copy the code
Thread method
The following table lists some important methods of the Thread class:
The serial number | Methods described |
---|---|
1 | public void start()Causes the thread to start executing;JavaThe VIRTUAL machine invokes the run method of the thread. |
2 | public void run()If the thread is constructed using a separate Runnable run object, the Runnable object’s run method is called. Otherwise, the method does nothing and returns. |
3 | public final void setName(String name)Change the thread name to be the same as the parameter name. |
4 | public final void setPriority(int priority)Changes the priority of a thread. |
5 | public final void setDaemon(boolean on)Mark this thread as a daemon thread or a user thread. |
6 | public final void join(long millisec)The maximum time to wait for this thread to terminate is Millis milliseconds. |
7 | public void interrupt()Interrupt the thread. |
8 | public final boolean isAlive()Tests whether the thread is active. |
Tests whether the thread is active. The above methods are called by the Thread object. The following methods are static methods of the Thread class.
The serial number | Methods described |
---|---|
1 | public static void yield()Suspends the currently executing thread object and executes the other threads. |
2 | public static void sleep(long millisec)Hibernates (suspends execution) the currently executing thread for a specified number of milliseconds, subject to the precision and accuracy of the system timer and scheduler. |
3 | public static boolean holdsLock(Object x)Returns true if and only if the current thread holds the monitor lock on the specified object. |
4 | public static Thread currentThread()Returns a reference to the thread object currently executing. |
5 | public static void dumpStack()Prints the stack trace for the current thread to the standard error stream. |
The instance
The following ThreadClassDemo program demonstrates some methods of the Thread class:
// File name: Displaymessage. Java public class DisplayMessage implements Runnable {private String message; public DisplayMessage(String message) { this.message = message; } public void run() { while(true) { System.out.println(message); Public class GuessANumber extends Thread {private int number; public GuessANumber(int number) { this.number = number; } public void run() { int counter = 0; int guess = 0; do { guess = (int) (Math.random() * 100 + 1); System.out.println(this.getName() + " guesses " + guess); counter++; }while(guess ! = number); System.out.println("** Correct! " + this.getName() + " in " + counter + " guesses.**"); }} // File name: ThreadClassDemo.java public class ThreadClassDemo { public static void main(String [] args) { Runnable hello = new DisplayMessage("Hello"); Thread thread1 = new Thread(hello); thread1.setDaemon(true); thread1.setName("hello"); System.out.println("Starting hello thread..." ); thread1.start(); Runnable bye = new DisplayMessage("Goodbye"); Thread thread2 = new Thread(bye); thread2.setPriority(Thread.MIN_PRIORITY); thread2.setDaemon(true); System.out.println("Starting goodbye thread..." ); thread2.start(); System.out.println("Starting thread3..." ); Thread thread3 = new GuessANumber(27); thread3.start(); try { thread3.join(); }catch(InterruptedException e) { System.out.println("Thread interrupted."); } System.out.println("Starting thread4..." ); Thread thread4 = new GuessANumber(75); thread4.start(); System.out.println("main() is ending..." ); }}Copy the code
The results are as follows, and the results vary from run to run.
Starting hello thread... Starting goodbye thread... Hello Hello Hello Hello Hello Hello Hello Hello Hello Thread-2 guesses 27 Hello ** Correct! Thread-2 in 102 guesses.** Hello Starting thread4... Hello Hello .......... remaining result produced.Copy the code
The main concepts of threads are:
Here are some concepts you need to understand when multithreading:
- Thread synchronization
- Interthread communication
- The thread deadlock
- Thread control: suspend, stop, and resume
Use of multithreading
The key to using multithreading effectively is to understand that programs execute concurrently rather than sequentially. For example, if you have two subsystems that need to be executed concurrently, you need to use multithreading.
Through the use of multithreading, you can write a very efficient program. Note, however, that if you create too many threads, the program actually performs less efficiently, not more efficiently.
Remember, context switching overhead is also important, if you create too many threads, the CPU will spend more time context switching than executing the program!