Java, multithreading, reflection

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...");
    }
}

Keywords: Java Back-end

Added by alexus on Wed, 23 Feb 2022 15:54:33 +0200