Multithreading
What is a process
A process is an application
What is a thread
A thread is an execution scenario / progression unit in a process
A process can start multiple threads
For java program, when entering in DOS command window:
After entering the java HelloWorld.
The JVM will be started first, and the JVM is a process
At the same time, start a garbage collection thread to take care of and collect garbage
At the very least, java programs now have at least two concurrent threads, one is the garbage collection thread, and the other is the main thread executing the main method
The memory of process A and process B is independent and not shared
Thread A and thread B, in java language: thread A and thread B, heap memory and method area memory are shared. However, the stack memory is independent, one thread and one stack
Assuming that 10 threads are started, there will be 10 stack spaces. Each stack does not interfere with each other and executes its own, which is multi-threaded concurrency
The purpose of multithreading mechanism in java is to improve the processing efficiency of the program
What is true multithreading concurrency
t1 thread executes t1
t2 thread executes t2
t1 does not affect t2, and t2 does not affect t1. This is called true multithreading concurrency
How to implement multithreading in java:
1. Write a class that directly inherits Java Lang. thread, override the run method
2. Write a class to implement Java Lang. runnable interface
The second method is commonly used to implement interfaces, because a class implements interfaces and can inherit other classes, which is more flexible
About the lifecycle of Thread objects
New status
Ready status
running state
Blocking state
State of death
What are the common thread scheduling?
Preemptive scheduling model:
Which thread has a higher priority, the probability of grabbing CPU time slice is higher
java adopts preemptive scheduling model
Even fraction scheduling model
Allocate CPU time slices evenly, and each thread occupies the same length of CPU time
Equal distribution, all equal
What methods are provided in java that are related to thread scheduling?
Example method
void setPriority(int newPriority) sets the priority of the thread
int getPriority() gets the priority of the thread
The minimum finite level is 1
The default finite level is 5
The highest priority is 10
Those with higher priority may get more CPU time slices (but not exactly, the probability is more)
Static method
static void yield() yield method
Pauses the currently executing thread object and executes other threads
The yield() method is not a blocking method. Make the current thread give way to other threads.
The execution of the yield() method will return the current thread from the "running state" to the "ready state" instance method
void join()
Merge thread
class MyThrea1 extends Thread { public void doSome() { MyThrea2 t = new MyThrea2(); t.join(); // The current thread enters blocking, and t thread executes until t thread ends. The current thread can execute normally } } class MyThrea2 extends Thread { }
a key
Data security in multithreaded concurrent environment.
In future development, our projects are running in the server East, and the server has completed the definition of thread, the creation of thread object, the startup of thread, etc. We don't need to write any of this code
The most important thing is: the program needs to be run in a multithreaded environment. Pay attention to whether these data are safe in a multithreaded concurrent environment
How to solve the thread safety problem?
When there is shared data in the environment of multithreading concurrency, and the data will be modified, there is a thread safety problem
Threads are queued for execution. (cannot be concurrent)
Queue execution is used to solve the problem of thread safety.
This mechanism is called thread synchronization mechanism
The technical term is called thread synchronization. In fact, threads cannot be concurrent, and threads must be queued for execution
Thread queuing will sacrifice some efficiency. Data security comes first, and only data security. We can talk about efficiency. Data is unsafe and inefficient
Asynchronous programming model:
Thread t1 and thread t2 execute their own, t1 regardless of t2, t2 regardless of t1
No one needs to wait. This programming model is called asynchronous programming model
Actually: multithreading concurrency (high efficiency)
Synchronous programming model:
For thread t1 and thread t2, when thread t1 executes, you must wait for the execution of thread t2 to end. In other words, when t2 thread executes, you must wait for t1 thread to finish executing.
There is a waiting relationship between two threads, which is the synchronous programming model (less efficient)
The syntax of thread synchronization mechanism is:
synchronized() {
/ / thread synchronization code block
}
The "data" passed in parentheses after synchronized is quite critical.
This data must be shared by multiple threads to achieve multi-threaded queuing
What is written in () of synchronized()?
It depends on which threads you want to synchronize
Suppose t1,t2,t3,t4,t5 have five threads
You just want t1,t2,t3 to queue, t4,t5 not to queue. What should I do?
Be sure to write a t1,t2,t3 shared object in (). This object is not shared for T4 and T5
In the java language, any object has a "lock". In fact, this lock is a tag. (just call it a lock)
100 objects, 100 locks. One object and one lock.
Execution principle of thread code
1. Assuming that t1 and t2 threads are concurrent, there must be one after the other when starting to execute the code
2. Suppose line t1 executes and encounters synchronized, it will automatically find the object lock of "shared object later", find and occupy the lock, and then execute the program in the synchronization code block. In the process of program execution, it is consistent to occupy the lock. The lock will not be released until the synchronization code block is completed.
3. Suppose t1 has already occupied the lock. At this time, when t2 page encounters the synchronized keyword, it will also occupy the lock of the shared object. As a result, the lock is occupied by t1. t2 can only wait outside the synchronization code block for t1 to finish until t1 finishes executing the synchronization code, and t1 will return the lock. Then t2 will take possession of the lock
In this way, the thread is queued for execution.
It should be noted here that the shared object must be selected. This shared object must be shared by the thread objects you need to queue up to execute.
Three variables in java
Instance variables: in heap
Static variables: in the method area
Local variables: in stack
Among the above three variables:
There will never be a thread safety problem with local variables, because local variables are not shared. (one thread, one stack)
Local variables are in the stack. So local variables will never be shared
The instance variable is in the heap, and there is only one in the heap.
There is only one static variable in the method area.
The heap and method area are shared by multiple threads. Therefore, there may be thread safety problems
Local variable + constant: there will be no thread safety problem
Member variables: there may be thread safety issues
synchronized can only appear in this instance method
It indicates that the whole method body needs to be synchronized, resulting in low program execution efficiency. This method is not commonly used
Advantage: it just saves code
If the shared object is this and the code block to be synchronized is the whole method body, this method is recommended
If you use local variables
Recommended: StringBuilder
Because there is no thread safety problem with local variables.
StringBuffer is non thread safe.
Summary:
synchronized can be written in two ways:
First: synchronous code block (flexible)
Synchronized (thread shared object){
Synchronization code block;
}
Second: use synchronized on the instance method
Indicates that the shared object must be this
And the synchronization code block is the whole method body
Third: use synchronized on static methods
Indicates that class lock is not found.
Class lock has only one handle.
Even if 100 objects are created, there is only one such lock
How to solve thread safety problems in future development?
synchronized will reduce the execution efficiency of threads and lead to poor user experience. The user throughput of the system is reduced. Poor user experience. Choose the thread synchronization mechanism when you have to
The first scheme: try to use local variables instead of "instance variables and static variables"
The second scheme: if it must be an instance variable, you can consider creating multiple objects, so that the memory of the instance variable is not shared (one thread corresponds to one object, 100 threads correspond to 100 objects, and if the objects are not shared, there is no data security problem)
The third scheme: if you can't use local variables and create multiple objects, you can only choose synchronized, thread synchronization mechanism
Threads in java language are divided into two categories
One is user thread
One is daemon thread (background thread)
The most representative is the garbage collection thread (daemon thread)
The main thread is the user thread
Features of daemon thread:
Generally, the daemon thread is an endless loop. As long as all user threads end, the daemon thread ends automatically.
Where are daemon threads used?
The system data is automatically backed up at 00:00 every day.
This requires a timer, and we can set the timer as a daemon thread. Where is the consistency? Back up before 00:00. If all user threads end, the daemon thread will exit automatically, and there is no need for data backup.
timer
Function of timer
Execute specific programs at specific intervals
In the actual development, it is very common to execute a specific program at short intervals.
There are many ways in java
You can use the sleep method to sleep and set the sleep time. When you wake up at this time point, you can perform tasks. This method is the most primitive timer.
A timer has been written in the java class library: java util. Timer, you can use it directly.
However, this general method is rarely used in current development, because there are many high-level frameworks that support timed tasks.
In the actual development, the SpringTask framework provided in the Spring framework is widely used. As long as this framework is simply configured, it can complete the task of the timer.
TimerTask implements the Runner interface
The third way to implement threads
FutureTask mode to implement the Callable interface. (new features of JDK8)
The thread implemented in this way can obtain the return value of the thread.
The previous two methods are unable to get the thread return value because the run method returns void
reflection:
The system assigns a thread to execute a task. After the thread executes the task, there may be an execution result. How can we get the execution result
The third way is to implement the Callable interface
Advantages: get the execution result of the thread
Disadvantages: the efficiency is relatively low. When obtaining the execution result of t thread, the current thread is blocked and the efficiency is low
About the wait and notify methods in the Object class. (producer and consumer model)
a. The wait and notify methods are not methods of Thread objects, but methods of any java Object in java, because both are built-in to the Object class
b. Function of wait() method
--Put the thread active on the o object into a waiting state until it is awakened
--Release the lock of o object held by the previous thread
Object o = new Object();
o.wait();
c. Function of notify() method
--Wake up o the waiting thread on the object
--It's just a notification. It won't release the lock previously held on the o object
o.notify();
Producer and consumer model
The production thread is responsible for production and the consumption thread is responsible for consumption
Production threads and consumption threads need to be balanced
This is a special business requirement. In this special case, you need to use the wait method and notify method
The wait method and notify method are based on thread synchronization. Because multithreading needs to operate a warehouse at the same time. Thread safety issues
/* How to create thread objects? Just new How do I start a thread? Call the start() method of the thread object */ public class ThreadTest01 extends Thread{ public static void main(String[] args) { // Create a branch thread object MyThread myThread = new MyThread(); // Start thread // The function of the start() method is to start a branch thread and open up a new stack space in the JVM. After the code breaking task is completed, it ends instantly // The task of this code is to open a new stack space. As long as the new stack space is opened, the start() method ends. The thread starts successfully // The run method of the thread at the bottom of the stack will be called successfully (and the run method will be pressed at the bottom of the stack) // The run method is at the bottom of the branch stack and the main method is at the bottom of the main stack. Run and main are equal myThread.start(); // Here, the code still runs in the main thread. for(int i = 0; i < 1000; i++) { System.out.println("Main thread-->" + i); } } } class MyThread extends Thread { // Write a program. This section of Cheng Xun runs in the branch thread (branch stack) @Override public void run() { for (int i = 0; i < 1000; i++){ System.out.println("Branch thread-->" + i); } } }
public class ThreadTest02 { public static void main(String[] args) { // Create a runnable object MyRunnable myRunnable = new MyRunnable(); // Encapsulate the runnable object into a thread object Thread thread = new Thread(myRunnable); thread.start(); for (int i = 0; i < 1000; i++) { System.out.println("Main thread-->" + i); } } } // java only adopts single inheritance. The first one cannot inherit other classes class MyRunnable implements Runnable { @Override public void run() { for (int i = 0; i < 1000; i++) { System.out.println("Branch thread-->" + i); } } }
/* static Thread currentThread() Gets the current thread object Thread.currentThread() Thread object getName(); Gets the name of the thread Thread object setName(); Modify the name of the thread When the thread has no name set, what is the rule of the default name Thread-0 Thread-1 Thread-2 .... */ public class ThreadTest03 { public static void main(String[] args) { MyThread2 t1 = new MyThread2(); // Get current thread // Because this band appears in the main method, all current threads are the main thread Thread currentThread = Thread.currentThread(); System.out.println(currentThread.getName()); // Modify thread name t1.setName("t1"); // Gets the name of the thread String name = t1.getName(); System.out.println(name); // Start thread t1.start(); MyThread2 t2 = new MyThread2(); t2.start(); } } class MyThread2 extends Thread { @Override public void run() { Thread thread = Thread.currentThread(); // Which thread executes the run method and outputs the same thread System.out.println(thread.getName()); for (int i = 0; i < 100; i++) { System.out.println("Branch thread" + i); } } }
/* About the sleep method of thread: static void sleep(long millis) 1.Static method: thread sleep(1000); 2.The parameter is milliseconds 3.Function: put the current thread into sleep, enter the "blocking state", give up occupying CPU time slice and give it to other threads. */ public class ThreadTest04 { public static void main(String[] args) { // Let the current thread sleep for 5s try { Thread.sleep(1000*5); } catch (InterruptedException e) { e.printStackTrace(); } // Execute the code here in 5 seconds System.out.println("hello world!"); for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + "-->" + i); // Sleep for 1 second try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } // About thread Interview questions of sleep () method // Create thread object MyThread3 t = new MyThread3(); t.setName("t3"); t.start(); // Call sleep method try { // Will this code put the thread t into sleep // Sleep is a static method, which will still be converted to: thread sleep(1000*5) // That is, it will put the main thread into sleep t.sleep(1000*5); } catch (InterruptedException e) { e.printStackTrace(); } } } class MyThread3 extends Thread { @Override public void run() { for (int i = 0; i < 1000; i++) { System.out.println(Thread.currentThread().getName() + "-->" + i); } } }
/* End sleep Thread object interrupt(); */ public class ThreadTest05 { public static void main(String[] args) { MyRunnable2 mr = new MyRunnable2(); Thread t = new Thread(mr); t.setName("t1"); // I hope the t thread wakes up after 5 seconds try { Thread.sleep(1000 *5); } catch (InterruptedException e) { e.printStackTrace(); } // Sleep of terminating t thread // This method relies on the exception handling mechanism of java (let sleep throw exceptions and end sleep) t.interrupt(); // interfere } } class MyRunnable2 implements Runnable { // Important: exceptions in run() can't throw, only try catch @Override public void run() { System.out.println(Thread.currentThread().getName() + "-->" + "begin"); // The exception at this time cannot be thrown, because throws cannot be larger than the exception of the parent class // There is no throws exception in the Runnable interface. So you cannot throw exception at this time try { Thread.sleep(1000 * 60 * 60 * 60); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "-->" + "end"); } }
/* Thread object stop() forcibly terminates the t thread Disadvantages: This method directly kills the thread and is easy to lose data The following methods are safer */ public class ThreadTest06 { public static void main(String[] args) { MyRunnable3 r = new MyRunnable3(); Thread t = new Thread(r); t.setName("t"); t.start(); // Analog 5s try { Thread.sleep(1000 * 5); } catch (InterruptedException e) { e.printStackTrace(); } // Forcibly terminate t thread after 5s // t.stop(); // Obsolete and not recommended // Terminate thread // If you want to terminate the execution of t during sleep, just change the flag to false r.run = false; } } class MyRunnable3 implements Runnable { // Make a Boolean mark boolean run = true; @Override public void run() { if (run) { for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + "-->" + i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } else { // return is over. Is there anything you haven't saved before it is over // You can save it off the face here // Terminate the current thread return; } } }
// priority public class ThreadTest07 { public static void main(String[] args) { System.out.println("Highest priority" + Thread.MAX_PRIORITY); System.out.println("Lowest priority" + Thread.MIN_PRIORITY); System.out.println("Default Priority " + Thread.NORM_PRIORITY); // Get the current thread object and get the priority of the current thread Thread currentThread = Thread.currentThread(); System.out.println(currentThread.getName() + "The default priority for threads is:" + currentThread.getPriority()); Thread t = new Thread(new MyRunnable4()); t.setPriority(10); t.setName("t"); t.start(); // The priority is relatively high, but the CPU time slice is relatively more for (int i = 0; i < 1000; i++) { System.out.println(Thread.currentThread().getName() + "-->" + i); } } } class MyRunnable4 implements Runnable { @Override public void run() { // Get thread finite level // System.out.println(Thread.currentThread().getName() + "default priority of thread:" + thread currentThread(). getPriority()); for (int i = 0; i < 1000; i++) { System.out.println(Thread.currentThread().getName() + "-->" + i); } } }
/* Thread abdication The current thread pauses, returns to the ready state and gives up to other threads Static method Thread.yield(); */ public class ThreadTest08 { public static void main(String[] args) { Thread t = new Thread(new MyRunnable5()); t.setName("t"); t.start(); for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + "-->" + i); } } } class MyRunnable5 implements Runnable { @Override public void run() { // Get thread finite level // System.out.println(Thread.currentThread().getName() + "default priority of thread:" + thread currentThread(). getPriority()); // Give way every 100 for (int i = 0; i < 1000; i++) { if (i % 100 == 0) { Thread.yield(); // The current thread ends and gives up to the main thread } System.out.println(Thread.currentThread().getName() + "-->" + i); } } }
/* Thread merging */ public class ThreadTest09 { public static void main(String[] args) { System.out.println("main begin"); Thread t = new Thread(new MyRunnable6()); t.setName("t"); t.start(); // Merge thread try { t.join(); // t is merged into the current thread. The current line is blocked, and the t thread executes until the end } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("main over"); } } class MyRunnable6 implements Runnable { @Override public void run() { // Get thread finite level // System.out.println(Thread.currentThread().getName() + "default priority of thread:" + thread currentThread(). getPriority()); // Give way every 100 for (int i = 0; i < 1000; i++) { System.out.println(Thread.currentThread().getName() + "-->" + i); } } }
// bank account // Thread safety problem occurs when multiple threads withdraw money from the same account // Thread synchronization mechanism can be used to solve thread safety problems public class Account { // account number private String actno; // balance private double balance; Object obj = new Object(); public Account() { } public Account(String actno, double balance) { this.actno = actno; this.balance = balance; } public String getActno() { return actno; } public void setActno(String actno) { this.actno = actno; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } // Method of withdrawal // Public synchronized void withraw (double money) {/ / this shared variable is locked public void withdraw(double money) { Object obj2 = new Object(); // The shared object here is: account object. // If the account object is shared, this is the account object // It's not necessarily this. Here, it's just the object shared by multiple threads // synchronized (obj) {/ / obj is an instance variable and a shared variable. Yes // synchronized (obj2) {/ / at this time, obj2 is a local variable, and a new object is generated every time you run it. It is not a shared variable. No // Synchronized ("ABC") {/ / "ABC" is in the string constant pool. Yes. In this way, all threads will be synchronized synchronized (this) { // Balance before withdrawal double before = this.balance; // Balance after withdrawal double after = before - money; // Simulate network latency try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } // Update balance // I haven't added synchronized t1 to execute here. I haven't had time to execute this line of code. t2 thread comes in withraw method. There must be something wrong at this time this.setBalance(after); } } } /// public class AccountThread extends Thread { // Two threads must share the same account object private Account act = null; // Pass the account object through the construction method public AccountThread(Account act) { this.act = act; } @Override public void run() { // The execution of the run method indicates the withdrawal operation // If you withdraw 5000 double money = 5000; // withdraw money act.withdraw(money); /* It can also be written here, but it will be less efficient if the scope is larger synchronized (act) { act.withdraw(money); } */ System.out.println("account" + act.getActno() + "balance:" + act.getBalance()); } } /// public class Test01 { public static void main(String[] args) { // Create account object (only one) Account act = new Account("act-001", 10000); // Create two threads AccountThread t1 = new AccountThread(act); AccountThread t2 = new AccountThread(act); // Set name t1.setName("t1"); t2.setName("t2"); // Start thread t1.start(); t2.start(); } }
// Interview questions /* doOther Does the execution of the method need to wait for the end of the doSome method No, because there is no synchronized t2 thread in the doOther method, this lock is not required No queue */ public class Exam01 { public static void main(String[] args) { MyClass mc = new MyClass(); Thread t1 = new MyThread(mc); Thread t2 = new MyThread(mc); t1.setName("t1"); t2.setName("t2"); t1.start(); // This sleep is to ensure that t1 is executed first try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); } } class MyThread extends Thread { private MyClass mc; public MyThread(MyClass mc) { this.mc = mc; } @Override public void run() { if(Thread.currentThread().getName() == "t1") { mc.doSome(); } if(Thread.currentThread().getName() == "t2") { mc.doOther(); } } } class MyClass { public synchronized void doSome() { System.out.println("doSome begin"); try { Thread.sleep(1000 * 10); } catch (InterruptedException e) { e.printStackTrace(); } } public void doOther() { System.out.println("doOther begin"); System.out.println("doOther over"); } }
// deadlock public class DeadLock { public static void main(String[] args) { Object o1 = new Object(); Object o2 = new Object(); MyThread1 t1 = new MyThread1(o1, o2); MyThread2 t2 = new MyThread2(o1, o2); t1.start(); t2.start(); } } class MyThread1 extends Thread { Object o1; Object o2; public MyThread1(Object o1, Object o2) { this.o1 = o1; this.o2 = o2; } @Override public void run() { synchronized (o1) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (o2) { } } } } class MyThread2 extends Thread { Object o1; Object o2; public MyThread2(Object o1, Object o2) { this.o1 = o1; this.o2 = o2; } @Override public void run() { synchronized (o2) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (o1) { } } } }
// Daemon thread public class ThreadTest10 { public static void main(String[] args) { BakDataThread t = new BakDataThread(); t.setName("Thread for backing up data"); // Before starting, set the thread as a daemon thread t.setDaemon(true); t.start(); // The main thread is the user thread for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + "-->" + i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } // Backup data class BakDataThread extends Thread { @Override public void run() { int i = 10; while (true) { System.out.println(Thread.currentThread().getName() + "-->" + ++i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
// The JUC package is a java Concurrent package, which is not available in the old JDK import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; /* The third way to implement threads Implement Callable The advantage is to obtain the execution result of the thread Disadvantages: the efficiency is relatively low. When obtaining the execution result of t thread, the current thread is blocked and the efficiency is low */ public class ThreadTest11 { public static void main(String[] args) throws Exception{ // Step 1: create a "future task class" object // Parameters are very important. You need to implement class objects for a Callable interface FutureTask task = new FutureTask(new Callable() { @Override public Object call() throws Exception { // The call() method is equivalent to the run method. But this one has a return value // A thread executes a task, and there may be an execution result after execution // Simulated execution System.out.println("call method begin"); Thread.sleep(1000 * 10); System.out.println("call method end!"); int a = 100; int b = 200; return a + b; // Automatic boxing (300 programming Integer) } }); // Create thread object Thread t = new Thread(task); t.start(); // Here is the main method, which is in the main thread // In the main thread, how to get the return result of t thread // The execution of the get method will cause the current thread to block Object obj = task.get(); // The program with the main method here must wait for the end of the get() method to execute // The get() method may take a long time. Because the get() method is used to get the execution result of another thread // Another thread takes time to execute } }
import java.util.ArrayList; import java.util.List; /* Using wait method and notify method to realize "producer and consumer mode" Simulation requirements The warehouse adopts List collection List It is assumed that only one element can be stored in the collection One element indicates that the warehouse is full If the number of elements in the list set is 0, it means that the warehouse is empty Ensure that at most one element is always stored in the list collection This effect must be achieved: one production, one consumption */ public class ThreadTest12 { public static void main(String[] args) { // Create warehouse object, shared List list = new ArrayList(); // Create two thread objects // Producer thread Thread t1 = new Thread(new Producer(list)); // Consumer thread Thread t2 = new Thread(new Consumer(list)); t1.setName("Producer thread"); t2.setName("Consumer thread"); } } // Production thread class Producer implements Runnable { // Warehouse private List list; public Producer(List list) { this.list = list; } @Override public void run() { // Continuous production (use dead cycle to simulate continuous production) while (true) { // Lock warehouse objects synchronized (list) { if (list.size() > 0) { // The current thread enters the waiting state and releases the lock of the list collection try { list.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } // If it can be executed here, it means that the warehouse is empty Object o = new Object(); list.add(o); System.out.println(Thread.currentThread().getName() + "-->" + o); // Awaken consumer consumption list.notifyAll(); } } } } // Consumption thread class Consumer implements Runnable { // Warehouse private List list; public Consumer(List list) { this.list = list; } @Override public void run() { // Always consumption while(true) { synchronized (list) { // Warehouse is empty if (list.size() == 0) { try { // The current thread enters the waiting lock list.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } // If the program can be executed to this point, it means that the warehouse is not empty and needs to be consumed Object o = list.remove(0); System.out.println(); System.out.println(Thread.currentThread().getName() + "-->" + o); // Awaken producer production list.notifyAll(); } } } }
reflex
What is the role of reflection mechanism?
Bytecode files can be manipulated through the reflection mechanism of java language.
The advantages are similar to hackers. (bytecode files can be read and modified)
Under which package is the reflection mechanism
java.lang.reflect.*;
What are the important classes related to reflection mechanism?
java.lang.Class :
Represents byte file, represents a type, and represents the whole class
java.lang.reflect.Method :
Represents the method bytecode in bytecode. Represents a method in a class
java.lang.reflect.Constructor :
Represents the construction method in bytecode. Bytecode represents the construction method in class
java.lang.reflect.Field :
Represents the attribute bytecode in bytecode. Represents member variables in the class (static variables + instance variables)
Three ways to get the bytecode of a class
1.Class c = Class.forName("full class name with package name");
2.Class c = reference getClass();
3.Class c = any type class
Instantiate the object through the newInstance() method of Class.
Note: the parameterless construction method is actually called inside the newInstance() method, and the parameterless construction must be guaranteed to exist.
Points to the bytecode in the method area
import java.util.Date; /* Class.forName() Static method The argument to the method is a string The character parameter is a complete class name The full class name must have the package name. java.lang packages cannot be omitted */ public class ReflectTest01 { public static void main(String[] args) { // The first way Class c1 = null; try { c1 = Class.forName("java.lang.String"); } catch (ClassNotFoundException e) { e.printStackTrace(); } // The second way // Any object in java has a method: getClass() String s = "abc"; // x stands for String Class bytecode file, x represents String type. Class x = s.getClass(); // The memory addresses stored in c1 and x are the same System.out.println(c1 == x); // true // Third: any type in java language, including basic data type, he has class attribute Class z = String.class; Class k = Date.class; Class f = int.class; Class e = double.class; System.out.println(x == z); // true } }
public class ReflectTest03 { public static void main(String[] args) { try { // Class. The execution of the forname() method will result in: class loading (static code blocks will be executed when the class is loaded) Class.forName("com.thintime.demo03.MyClass"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } class MyClass { // The static code block is executed when the class is loaded, and only once static { System.out.println("MyClass The static code block of class has been executed!"); } }
public class Student { public int no; private String name; protected int age; boolean sex; private static final double MATH_PI = 3.14159267; }
import java.lang.reflect.Field; import java.lang.reflect.Modifier; // Reflecting access to properties in a class public class ReflectTest04 { public static void main(String[] args) throws Exception { Class stuClass = Class.forName("com.thintime.demo03.Student"); String className = stuClass.getName(); System.out.println("Full class name:" + className); String simpleName = stuClass.getSimpleName(); System.out.println("Simple class name:" + simpleName); // Get properties in class Field[] fields = stuClass.getFields(); System.out.println(fields.length); // 1 has only one element // Take out the name of this Field Field f = fields[0]; String fieldName = f.getName(); System.out.println(fieldName); // no // Get all properties in the class Field[] dFields = stuClass.getDeclaredFields(); System.out.println(dFields.length); // 5 for (Field field : dFields) { // Gets the type of the property Class type = field.getType(); String typeName = type.getSimpleName(); System.out.println(typeName); // Gets the name of the property String fieldName2 = field.getName(); System.out.println(fieldName2); // Gets the list of modifiers for the property // The returned modifier is a number, and each number is the code of the modifier! int modifiers = field.getModifiers(); System.out.println(modifiers); // Converts the modifier code to a string String modifierString = Modifier.toString(modifiers); System.out.println(modifierString); } } }
public class ReflectTest05 { public static void main(String[] args) throws Exception{ Class stuClass = Class.forName("com.thintime.demo03.Student"); Object obj = stuClass.newInstance(); // Use reflection to access a property of an object // Get Field by attribute name Field noField = stuClass.getDeclaredField("no"); // Assign a value to the no attribute of the obj object (Student object) noField.set(obj, 2222); // Assign value to no attribute of obj object // Read the value of the property Object o = noField.get(obj); System.out.println(o); // Access private properties Field nameField = stuClass.getDeclaredField("name"); // Break the package nameField.setAccessible(true); // Assign a value to the name attribute nameField.set(obj, "Tom"); // Get the value of name System.out.println(nameField.get(obj)); // Tom } }
import java.lang.reflect.Method; /* The reflection mechanism calls the method of an object Reflection mechanism makes the code very general, and the changeable contents are written to the configuration file After modifying the configuration in the future, the objects created and the methods called will be different */ public class ReflectTest06 { public static void main(String[] args) throws Exception{ // Get class Class userServiceClass = Class.forName("com.thintime.demo03.UserService"); // Get all methods (including private ones) Method[] methods = userServiceClass.getDeclaredMethods(); // Traversal Method for (Method method : methods) { // Gets the return value type of the method Class returnType = method.getReturnType(); System.out.println(returnType.getSimpleName()); // Get method name System.out.println(method.getName()); // Gets a list of parameter types for the method Class[] parameterTypes = method.getParameterTypes(); for (Class type : parameterTypes) { System.out.println(type.getSimpleName()); } // Acquisition method Method login = userServiceClass.getDeclaredMethod("login", String.class, String.class); // Call method Object obj = userServiceClass.newInstance(); Object returnValue = login.invoke(obj, "admin", "123"); System.out.println(returnValue); } } } class UserService { /** * Login method * @param name user name * @param password password * @return true Indicates successful login and false indicates failed login */ public boolean login(String name, String password) { if ("admin".equals(name) && "123".equals(password)) { return true; } return false; } // Method of exiting the system public void logout() { System.out.println("The system has exited safely!"); } }
import java.lang.reflect.Constructor; // Get the construction method using reflection mechanism public class ReflectTest07 { public static void main(String[] args) throws Exception{ // Create objects using the reflection mechanism Class vipClass = Class.forName("com.thintime.demo03.Vip"); // Call parameterless constructor Object obj = vipClass.newInstance(); // Call parameterized constructor // 1. Get the parameter construction method first Constructor con = vipClass.getDeclaredConstructor(int.class, String.class, String.class, boolean.class); // 2. Call construction method to create object Object tom = con.newInstance(100, "Tom", "2022-01-01", true); // Get parameterless construction method Constructor con2 = vipClass.getDeclaredConstructor(); Object newObj2 = con2.newInstance(); } } class Vip { int no; String name; String birth; boolean sex; public Vip() { } public Vip(int no, String name, String birth, boolean sex) { this.no = no; this.name = name; this.birth = birth; this.sex = sex; } }
/* Get the parent class and interface of the class through reflection */ public class ReflectTest08 { public static void main(String[] args) throws Exception{ // String type Class strClass = Class.forName("java.lang.String"); // Get the parent class of String Class superclass = strClass.getSuperclass(); System.out.println(superclass.getSimpleName()); // Gets all interfaces implemented by the String class Class[] strClassInterfaces = strClass.getInterfaces(); for (Class in : strClassInterfaces) { System.out.println(in.getSimpleName()); } } }
About the built-in class loader in JDK
What is a class loader?
Commands / tools specifically responsible for loading classes
ClassLoader
JDK comes with three class loaders
Start class loader
extensions class loader
Application class loader
If there is a code:
String s = "abc";
Before the code starts executing, all the required classes will be loaded into the JVM
Load through the class loader. When you see the above code, the class loader will find string Class file, find it and load it
First, load through the "start class loader".
Note: the boot class loader specifically loads: jdk1 8.0_ 101\jre\lib\rt.jar
rt.jar is the core class library of JDK.
If it cannot be loaded through the "start class loader", it will be loaded through the "extended class loader"
Note: the "extension class loader" loads: jdk1 8.0_ 101\jre\lib\ext\*. jar
If it cannot be loaded through the "extension class loader", it will be loaded through the "Application Loader"
Note: the "Application Loader" specifically loads the jar package in the classpath (the path to configure environment variables)
In order to ensure the security of class loading, the two parent delegation mechanism is used in java.
Priority is given to loading from the boot class loader, which is called "parent"
"Parent" cannot be loaded into. It is called "parent" when it is loaded from the extension class loader
Parental delegation. If it cannot be loaded, it will be considered to load from the application loader
import java.io.FileReader; public class AboutPath { public static void main(String[] args) throws Exception { // Disadvantages of this method: poor value shifting. The default current path in IDEA is the root path of project // This code assumes that if you leave the IDEA and change to another location, the current path may not be the root path of the project FileReader fr = new FileReader("day04/testFile.properties"); // The following method is still common even if the code changes position // Note: the premise of using the following general method is that this file must be in the classpath // What is classpath? All under src are under classpath // src is the root path of the class /* Thread.currentThread() Current thread object getContextClassLoader() The method of thread object can obtain the classloader object of the current thread. getResource() The method of the classloader object. The current thread classloader loads resources from the root path of the class by default */ String path = Thread.currentThread().getContextClassLoader().getResource("testFile2.properties").getPath(); System.out.println(path); // /D:/workspace/javabase/out/production/day04/testFile2.properties // Start from the lower path of the class String path2 = Thread.currentThread().getContextClassLoader().getResource("com\\thintime\\demo03\\test.properties").getPath(); System.out.println(path2); // /D:/workspace/javabase/out/production/day04/com%5cthintime%5cdemo03%5ctest.properties } }
import java.util.ResourceBundle; /* java.util A resource binder is provided under the package to obtain the content in the attribute configuration file When using this method, the attribute configuration file must be placed under the classpath. And when writing the path, the extension behind the path cannot be written */ public class ResourceBundleTest { public static void main(String[] args) { ResourceBundle bundle = ResourceBundle.getBundle("testFile2"); // className=com.thintime.demo03.User String className = bundle.getString("className"); System.out.println(className); // com.thintime.demo03.User ResourceBundle bundle2 = ResourceBundle.getBundle("com\\thintime\\demo03\\test.properties"); } }
Variable length parameter
int... args this is the variable length parameter
The syntax is: type (Note: it must be 3 points)
a. The number of parameters required for variable length parameters is: 0~N
b. Variable length parameter must be in the last position in the parameter list, and there can only be one variable length parameter
c. Variable length parameters can be viewed as an array
/* Variable length parameter */ public class ArgsTest { public static void main(String[] args) { method1(); method1(1); method1(1,2,3); method1(new int[]{1,2,3,5}); method2("abc"); method2("ccc", 2, 4); // 2 4 } public static void method1(int... args) { System.out.println("m Method executed"); } public static void method2(String s, int... args) { System.out.println("m Method executed"); for (int arg : args) { System.out.print(arg); } } }
annotation
Or Annotation, the English word is: Annotation
Annotation is a kind of reference data type, which generates XXX after compilation class
The attribute types of annotations can be:
byte short int long float double boolean char String Class enumeration type
And the data form of each of the above
How to customize annotations? Syntax format?
[modifier list] @ interface annotation type name{
}
How and where are annotations used?
1. The syntax format of annotation is:
@ annotation type name
2. Annotations can appear on classes, attributes, methods, variables, etc
Annotations can also appear on annotation types
JDK built-in annotation
java.lang package includes the following annotation types:
a.Deprecated a program element annotated with @ deprecated. Programmers are not encouraged to use such an element, usually because it is dangerous or there is a better choice
b. Override indicates that a method declaration intends to override another method declaration of a superclass
c. Suppresswarnings are just compiler warnings that should be specified in a comment element (all program elements already included in the comment element)
@Overrite annotation can only annotate methods
Meta annotation
Annotation used to mark annotation type
Common meta annotations
Target
Retention
Notes on Target:
It is used to mark where the "marked Annotation" can appear
Notes on Retention:
Used to mark where the "annotated Annotation" is finally saved
@Retention(RetentionPolicy.SOURCE): indicates that the annotation is only retained in the java source file
@Retention(RetentionPolicy.CLASS): indicates that the annotation is saved in the class file
@Retention(RetentionPolicy.RUNTIME): indicates that the annotation is saved in the class file and can be read by the reflection mechanism
If the attribute name of an annotation is value, and there is only one attribute. When used, the attribute name can be omitted
/* Custom annotation: MyAnnotation */ import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; // Only this annotation is allowed. Only classes and methods can be marked @Target({ElementType.METHOD,ElementType.TYPE}) // I hope this annotation can be reflected @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { /* Generally, attributes can be defined in annotations. The following is the name attribute of MyAnnotation It looks like a method, but it's actually the one called the attribute name */ String name(); String color(); int age() default 25; // Property to specify the default value } /// public @interface MyAnnotation2 { // When the attribute is value, the annotated attribute name can be left blank String value(); } /// import java.lang.reflect.Method; public class AnnotationTest01 { // If there is an attribute in an annotation, the attribute must be assigned a value // If there is a default value, it can not be added @MyAnnotation(name = "Tom", color = "Green") public void doSome() { System.out.println("doSome..."); } // //When the attribute is value, the annotated attribute name can be left blank @MyAnnotation2("abc") public void doOther() { System.out.println("doOther..."); } public static void main(String[] args) throws Exception{ Class myAnn = Class.forName("com.thintime.demo01.MyAnnotation"); // Judge whether there is @ MyAnnotation on the class System.out.println(myAnn.isAnnotationPresent(MyAnnotation.class)); Class annTest = Class.forName("com.thintime.demo01.AnnotationTest01"); Method doSome = annTest.getDeclaredMethod("doSome"); // Determine whether this annotation exists on the method if (doSome.isAnnotationPresent(MyAnnotation.class)) { MyAnnotation ann = doSome.getDeclaredAnnotation(MyAnnotation.class); System.out.println(ann.name()); System.out.println(ann.color()); } } }
// Indicates that this class is obsolete @Deprecated public class AnnotationTest03 { public static void main(String[] args) { AnnotationTest03.doSome(); } // Indicates that this method is outdated @Deprecated public static void doSome() { System.out.println("doSome..."); } public static void doOther() { System.out.println("doOther..."); } }