Multithreading
1.1 basic concepts: program, process and thread
- Program: a set of instructions written in a certain language to complete a specific task. It refers to a piece of static code, static object
- Process: it is an execution process of a program or a running program. It is a dynamic process: it has its own process of emergence, existence and extinction—— Declaration period
- Such as QQ in operation
-The program is static and the process is dynamic - As a unit of resource allocation, the system will allocate different memory areas for each process at run time
- Thread: a process can be further refined into a thread, which is an execution path within a program.
- If a process parallels multiple threads at the same time, it supports multiple threads
- Thread is the unit of scheduling and execution. Each thread has its own running stack and program counter (pc). The overhead of thread switching is small
- Multiple threads in a process share the same memory unit / memory address space - > they allocate objects from the same heap and can access the same variables and objects. This makes the communication between threads more simple and efficient. However, the sharing of system resources by multiple threads may bring security risks
***The virtual machine stack and program counter are one copy for one thread, while the method area and heap are one copy for one process. All threads share the method area and heap***
1.2 single core cpu and multi-core cpu:
- Single core CPU is actually A fake multithreading, because it can only execute one thread task at A time. If there are A and B thread tasks, the single core CPU executes one first, then hangs up, and then executes the other for A while, switching back and forth, but it can't feel it because the CPU time is very short;
- Multi core can give better play to multithreading
- A Java application has at least three threads: main() main thread, gc() garbage collection thread and exception handling thread
1.3 parallelism and concurrency
- Parallel: multiple CPU s execute multiple tasks at the same time
- Concurrency: one CPU (using time slice) executes multiple tasks at the same time
1.4 advantages of multithreading
1. Improve application impact. It is more meaningful to the graphical interface and can enhance the user experience
2. Improve CPU utilization
3. Improve the procedure structure. The long and complex process is divided into multiple threads and run independently, which is conducive to understanding and modification
When do I need multithreading
- The program needs to perform two or more tasks at the same time
- The program needs to realize some waiting tasks, such as user input, file reading and writing, etc
- Some background runtime programs are required
2 creation and use of threads
2.1 method 1: inherit Thread class
1. Create a subclass of Thread class
2. Rewrite the run() method of Thread class – > declare the operation of this Thread in the run method
3. Create subclass objects of Thread class
4. Call start() through this object
/** * * Multithreading creation method 1: basic Thrad class * * 1.Create a subclass of the underlying Thread class * * 2.Override the run() method of Thread class -- > declare the operation of this Thread in the run method * * 3.Create a subclass object of Thread class * * 4.start() is called through this object * */ //1. Create a subclass of Thread class class MyThread extends Thread{ // 2. Override the run() method of Thread class @Override public void run() { for (int i = 0; i <100 ; i++) { if(i%2==0){ System.out.println(i); } } } } public class ThreadTest { public static void main(String[] args) { // 3. Create subclass objects of Thread class MyThread t1 = new MyThread();//Done by the main thread // 4. Call start() through this object: 1. Start the current thread; 2 call the run() method of the current thread t1.start();//After the main thread does, the run() operation is the branch line //Question 1: it will not start a new thread, but just call the method or the main thread // t1.run(); //Problem 2: start a thread and traverse the even number within 100. The thread that has started () cannot be allowed to execute, and an exception will be reported // t1.start(); //Need to rewrite to create a thread object MyThread t2 = new MyThread(); t2.start(); // The following operations are still performed in the main thread for (int i = 0; i <100 ; i++) { if (i%2==0){ System.out.println(i+"=====main====="); } } } }
Joint learning: create two threads, one of which traverses an even number within 100 and the other traverses an odd number within 100
Method 1 public class ThreadDemo { public static void main(String[] args) { MyThread1 t1 = new MyThread1(); MyThread2 t2 = new MyThread2(); t1.start(); t2.start(); } } class MyThread1 extends Thread{ @Override public void run() { for (int i = 0; i <100 ; i++) { if(i%2==0){ System.out.println(Thread.currentThread().getName()+":"+i); } } } } class MyThread2 extends Thread{ @Override public void run() { for (int i = 0; i <100 ; i++) { if(i%2 !=0){ System.out.println(Thread.currentThread().getName()+":"+i); } } } }
Method 2 public class ThreadDemo { public static void main(String[] args) { // Create an anonymous subclass of Thread new Thread(){ @Override public void run() { for (int i = 0; i <100 ; i++) { if(i%2==0){ System.out.println(Thread.currentThread().getName()+":"+i); } } } }.start(); new Thread(){ @Override public void run() { for (int i = 0; i <100 ; i++) { if(i%2 !=0){ System.out.println(Thread.currentThread().getName()+":"+i); } } } }.start(); } }
2.2 common methods in thread
1.start(): start the current thread; Call the run() method of the current thread
2.run(): you usually need to override this method in the Thread class and declare the operation to be performed by the created Thread in this method
3.currentThread(): a static method that returns the thread executing the current code
4.getName(): get the name of the current thread
5.setName(): sets the name of the current thread
6.yield(): release the execution power of the current cpu (re rob)
7.join(): the join () method of calling thread B in thread A. At this point, thread A enters the blocking state, and A can stop blocking until the thread B is executed.
8.stop(): the thread is forced to end when this method is executed
9.sleep(long millitime): let the current thread "sleep" for the specified millitime milliseconds. Within the specified time, the current thread is blocked
10.isAlive(): judge whether the current thread is still alive
* test Thread Common methods in class HelloThread<publi> extends Thread{ @Override public void run() { for (int i = 0; i <100; i++) { if(i%2==0){ try { sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+":"+i); } if (i%20==0){ this.yield(); } } } public HelloThread(String name){ super(name); } } public class ThreadMethodTest { public static void main(String[] args) { //Name the thread by constructor HelloThread h1 = new HelloThread("Thread:1"); // h1.setName("thread one"); h1.start(); // Name the main thread Thread.currentThread().setName("Main thread"); for (int i = 0; i <100; i++) { if(i%2==0){ System.out.println(Thread.currentThread().getName()+":"+i); } if(i==20){ try { h1.join(); } catch (InterruptedException e) { e.printStackTrace(); } } } System.out.println(h1.isAlive()); } }
2.3 thread priority
- Thread priority level
- MAX_PRIORITY:10
- MIN_PRIORITY:1
- NORM_PRIORITY:5
- Methods involved:
- getPriority(): return thread priority value
- setPriority(int newPriority): change thread priority
- explain
- Inherit the priority of the parent class when the thread is created
- Low priority is only a low probability of obtaining scheduling, and it is not necessarily called after high priority
class HelloThread<publi> extends Thread{ @Override public void run() { for (int i = 0; i <100; i++) { if(i%2==0){ System.out.println(Thread.currentThread().getName()+getPriority()+":"+i); } if (i%20==0){ this.yield(); } } } public HelloThread(String name){ super(name); } } public class ThreadMethodTest { public static void main(String[] args) { //Name the thread by constructor HelloThread h1 = new HelloThread("Thread:one"); // h1.setName("thread one"); // Set the priority of threads h1.setPriority(Thread.MAX_PRIORITY); h1.start(); // Name the main thread Thread.currentThread().setName("Main thread"); Thread.currentThread().setPriority(Thread.MIN_PRIORITY); for (int i = 0; i <100; i++) { if(i%2==0){ System.out.println(Thread.currentThread().getName()+":"+Thread.currentThread().getPriority()+":"+i); } } } }
Joint learning: example: create three windows to sell tickets, and the total number of votes is 100
Thread safety problem, to be solved class Window extends Thread{ private static int ticket=100; @Override public void run() { while(true){ if (ticket > 0) { System.out.println(Thread.currentThread().getName() + ":Ticket number" + ticket); ticket--; } else { break; } } } } public class WindowTest { public static void main(String[] args) { Window t1=new Window(); Window t2=new Window(); Window t3=new Window(); t1.setName("Window 1"); t2.setName("Window 2"); t3.setName("Window 3"); t1.start(); t2.start(); t3.start(); } }
If you don't want to add static to the ticket, you need another way to create multithreading
2.4 mode 2: implement Runnable interface
1. Create a class that implements the Runnable interface
Method in the implementation of runnable class (. Runnable)
3. Create an object that implements the class
4. Pass this object as a parameter to the constructor of Thread class and create the object of Thread class
5. Call start() through the object of Thread class
//1. Create a class that implements the Runnable interface class MThread implements Runnable{ //2. Implement the class to implement the abstract method in Runnable: run() @Override public void run() { for (int i = 0; i <100; i++) { if(i%2==0){ System.out.println(Thread.currentThread().getName()+":"+i); } } } } public class ThreadTest1 { public static void main(String[] args) { //3. Create an object that implements the class MThread mThread = new MThread(); //4. Pass this object as a parameter to the constructor of Thread class and create the object of Thread class Thread t1 = new Thread(mThread); //5. Call start() through the object of Thread class; 1 start Thread 2 call current Thread run() -- > call run() of target in Runnable type t1.start(); //Start another thread and traverse the even number within 100 Thread t2 = new Thread(mThread); t2.start(); } }
Joint learning: example: create three windows to sell tickets, and the total number of votes is 100
//Thread safety problem, to be solved class Window1 implements Runnable{ private int ticket=100; @Override public void run() { while (true){ if (ticket>0){ System.out.println(Thread.currentThread().getName()+":Ticket number"+ticket); ticket--; }else { break; } } } } public class WindowRunnableTest { public static void main(String[] args) { Window1 w = new Window1(); Thread t1 = new Thread(w); Thread t2 = new Thread(w); Thread t3 = new Thread(w); t1.setName("Thread 1"); t2.setName("Thread 2"); t3.setName("Thread 3"); t1.start(); t2.start(); t3.start(); } }
2.5 comparison of the two methods
Priority in development: the way to implement Runnable interface
Reason: 1 The implementation method has no limitation of single inheritance of classes
2. The implementation method is more suitable for dealing with the situation that multiple threads share data
Connection: the Thread class itself also implements Runnable
The same point: both methods need to override run(), and declare the logic to be executed by the thread in run()
3 thread life cycle
Five states:
- New: when a Thread or its subclass is declared and created by an object
- Ready: after start(), the conditions for running are met, but the cpu resources are not allocated
- Run: when the ready program is scheduled and obtains CPU resources, it enters the running state. The run() method defines the operation and function of the thread
- Blocking: in a special case, when the · 1 I / O operation is suspended or executed artificially, give up the CPU and temporarily terminate its execution. Enter blocking state
- Death: the thread has completed all its work or the thread is forcibly terminated in advance or terminated abnormally
4 thread synchronization (solve thread safety problems)
1. Problem: there are duplicate tickets in the process of selling tickets. Wrong ticket – > thread security problem
2. Cause of the problem: when a thread operates the ticket and the operation has not been completed, other threads participate in the operation of the ticket
3. How to solve it: when a thread a is operating a ticket, other threads cannot participate. Other threads cannot start operating a ticket until the thread is finished. This situation cannot be changed even if thread a is blocked
4. In Java, we solve the thread safety problem through synchronization mechanism
Method 1: synchronize code blocks
Synchronized (synchronized monitor){
//Code to be synchronized
}
***Description: 1 The code that operates shared data, that is, the code that needs to be synchronized, cannot contain more or less codes
2. Shared data: data operated by multiple threads
3. Synchronous monitor, commonly known as lock. The object of any class can act as a lock
Requirement: multiple threads must share the same lock***
The synchronization code block solves the thread safety problem of implementing Runnable interface:
- Supplement: in the way of inheriting Thread class to create multithreading, carefully use this as the synchronization monitor, and consider using the current class as the synchronization monitor
class Window1 implements Runnable{ private int ticket=100; Object obj=new Object(); @Override public void run() { while (true){ synchronized (obj) { if (ticket > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":Ticket number" + ticket); ticket--; } else { break; } } } } } public class WindowRunnableTest { public static void main(String[] args) { Window1 w = new Window1(); Thread t1 = new Thread(w); Thread t2 = new Thread(w); Thread t3 = new Thread(w); t1.setName("Window 1"); t2.setName("Window 2"); t3.setName("Window 3"); t1.start(); t2.start(); t3.start(); } }
Synchronous code block solves the Thread safety problem of inheriting Thread:
- Supplement: in the way of inheriting Thread class to create multithreading, carefully use this as the synchronization monitor, and consider using the current class as the synchronization monitor
class Window extends Thread{ private static int ticket=100; private Object obj=new Object(); private static Object obj2=new Object(); @Override public void run() { while(true){ // synchronized (obj) {is not unique at this time synchronized (obj2){ if (ticket > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":Ticket number" + ticket); ticket--; } else { break; } } } } } public class WindowTest2 { public static void main(String[] args) { Window t1=new Window(); Window t2=new Window(); Window t3=new Window(); t1.setName("Window 1"); t2.setName("Window 2"); t3.setName("Window 3"); t1.start(); t2.start(); t3.start(); } }
Mode 2: synchronization method
5. Synchronization solves the problem of thread safety - benefits
When operating synchronization code, only one thread can participate and other threads wait. But with a single threaded process – limitations