Multithreading
Multi task execution
If there is no multitasking, multithreading is not required
program
Java source Program and bytecode file are called "Program", which is a static concept.
process
The program in execution is called process, which is a dynamic concept. In order for the computer program to run, the computer needs to load both code and data.
thread
Thread is the smallest unit that the operating system can schedule operations.
It is included in the process and is the actual operation unit in the process.
A thread refers to a single sequential control flow in a process. Multiple threads can be concurrent in a process, and each thread executes different tasks in parallel.
The difference between process and thread
difference | process | thread |
---|---|---|
Fundamental difference | Unit of resource allocation | Scheduling execution unit |
expenses | Each process has its own code and data space, and the switching between processes will have a large overhead | Threads can be regarded as lightweight processes. The same kind of threads share code and data space. Each thread has an independent program counter (PC), and the overhead of thread switching is small |
Environment | Multiple tasks can be run simultaneously in the operating system | Multiple sequential streams are executed simultaneously in the same application |
Allocate memory | When the system is running, it will allocate different memory areas for each process | All resources of the process are shared among threads, and each thread only has its own stack and local variables. Threads are independently scheduled and executed by the CPU. In a multi CPU environment, multiple threads are allowed to run at the same time |
Inclusion relation | A process without threads can be regarded as a single thread. If a process has multiple threads, the execution process is not one line, but multiple lines (threads) work together | Threads are part of a process, so threads are sometimes referred to as lightweight processes or lightweight processes |
The goal of learning multithreading
1. Create and enable multithreading (key)
2. Thread state
3. Thread safety (key)
3. Thread communication
Create and enable multithreading
1 inherit Thread class
Create an instance of the Thread subclass and override the run method, which will be executed automatically after calling the start() method
1) Create Thread class: inherit Thread class + override run() method
2) Construct thread class object: an object that creates a subclass
3) Start thread: call the start() method through a subclass object
//1) Create thread class public class Thread01 extends Thread{ //Override run() to define the thread body @Override public void run() { for(int i = 1;i<=20;i++){ System.out.println("Hee hee..."); try { Thread.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { //2) Construct thread class object Thread01 t01 = new Thread01(); //3) Start thread t01.start(); for(int i = 1;i<=20;i++){ System.out.println("ha-ha..."); try { Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } } } }
be careful:
Inherit parent class - > single inheritance
The run method cannot throw exceptions, but can only catch exceptions
The run method has no return value
Thread.sleep(): the specified number of milliseconds to sleep (temporarily stop execution) the currently executing thread
2. Implement Runnable interface (recommended)
1) Create the implementation class of Runnable interface + rewrite the run() method
2) Create an implementation class object
3) Create Thread class object with implementation class object
4) Start thread
advantage:
Simple, multiple interfaces can be implemented to realize resource sharing
//1) Create the implementation class of Runnable interface + rewrite the run() method public class Thread02 implements Runnable{ @Override public void run() { for (int i = 0; i <20; i++) { System.out.println("Hee hee!!!!!"); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args){ //2) Create an implementation class object Thread02 t02 = new Thread02(); //3) Create Thread class object with implementation class object Thread th = new Thread(t02); //4) Start thread th.start(); for (int i = 0; i <20; i++) { System.out.println("Hip Hop!!"); try { Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } } } }
Define the thread body through internal classes
public class Thread02 { //1) Create the implementation class of Runnable interface + rewrite the run() method static class Inner1 implements Runnable { @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println("Haha!!!!"); try { Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) { //Method 1: use local inner classes class Inner2 implements Runnable{ @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println("Hip Hop!!"); try { Thread.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } } } } //Create and start threads new Thread(new Inner1()).start(); new Thread(new Inner2()).start(); //Method 2: optimize local inner classes with anonymous inner classes new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 30; i++) { System.out.println("Hip Hop!!!!"); try { Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); //Method 3: optimize anonymous inner classes using Lambda new Thread(()->{ for (int i = 0; i < 30; i++) { System.out.println("Hip Hop!!!!"); try { Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } }
3. Callable interface (understand)
Create an implementation class that implements the Callable interface + rewrite the call() method
Callable interface under juc (java.util.concurrent) package
Advantages: exceptions can be thrown and return values can be defined
Disadvantages: complex use
public class Thread03 implements Callable<String> { @Override public String call() throws Exception { for (int i = 0; i < 20; i++) { System.out.println("Hee hee!!!!"); Thread.sleep(10); } return null; } public static void main(String[] args) throws ExecutionException, InterruptedException { //1. Create thread Thread03 t = new Thread03(); //2.1) create execution service ExecutorService es = Executors.newCachedThreadPool(); //2) Submit for execution Future<String> f = es.submit(t); for (int i = 0; i < 20; i++) { System.out.println("Hip hop!!"); Thread.sleep(3); } //3) Get execution results System.out.println(f.get()); } }
Similarities and differences of the three methods:
Thread: inheritance method, not recommended, because Java inherits by itself. If you inherit thread, you can't inherit other classes. It's not flexible enough
Runnable: implements the interface, which is more flexible than the Thread class and has no single inheritance restrictions. It is recommended
Callable: both Thread and Runnable are overridden run() methods with no return value. Callable is overridden call() method with return value
Thread pool
Thread pool is to create some threads first, and their collection is called thread pool
Using thread pool can improve performance very well. When the system starts, the thread pool creates a large number of idle threads. The program passes a task to the thread pool, and the thread pool will start a thread to execute the task. After execution, the thread will not die, but return to the thread pool to become idle again and wait for the execution of the next task.
Working mechanism of thread pool
In the programming mode of thread pool, the task is submitted to the whole thread pool rather than directly to a thread. After getting the task, the thread pool will look for whether there are idle threads internally. If so, the task will be handed over to an idle thread. A thread can only execute one task at the same time, but it can submit multiple tasks to a thread pool at the same time.
Status of the thread
1 newborn state
new Thread(): a new thread enters a new state
2 ready status
start(): a thread will enter the ready state, enter the ready queue and wait for cpu scheduling
3 operation status
When a cpu call is dispatched to a thread in the ready queue, the thread begins to enter the running state
4 blocking state
The thread cannot execute normally and may enter a blocking state
5 termination status
Thread execution completed
How to enter the ready state
1. start(): start the process
2. Thread switching: the switched thread returns to the ready state and waits for the next call
3. Unblock
4. yield(): yield thread
How to enter the blocking state
1,sleep()
2,join()
3,wait()
4. IO, etc
How to enter the termination state
1. stop() termination method – > is obsolete and is not recommended
2. Judge by adding logo – > recommended
3. Normal execution completed
be careful:
1) Once a thread is executed, it cannot be resumed, and new is also a new thread
2) When the blocking is removed, it cannot be directly restored to the running state. It will be restored to the ready state first and wait for the next CPU scheduling