what? Heard of these four concepts, many Java veterans have no idea!

what? Heard of these four concepts, many Java veterans have no idea!

Java is a programming language that many people have been using, but some Java concepts are very difficult to understand. Even some veterans for many years have some confusion and confusion about some Java concepts.
Therefore, in this article, we will introduce the four most difficult concepts in Java to help developers understand these concepts more clearly:
1. The usage of anonymous inner classes
2. Multithreading
3. How to achieve synchronization
4 .Serialization

Anonymous inner class

An anonymous inner class is also called an anonymous class. It is a bit like a local class or an inner class, except that the anonymous inner class has no name. We can declare and instantiate an anonymous inner class at the same time.
An anonymous inner class is only suitable for scenarios where you want to use a partial class and only use this partial class once.
An anonymous inner class does not have a constructor that needs to be explicitly declared, but there will be a hidden, automatically declared constructor.
There are two ways to create an anonymous inner class:
1. Create an anonymous inner class by inheriting a class (either concrete or abstract)
2. Create an anonymous inner class by implementing an interface
Let’s take a look at the following example:


interface Programmer {
    void develop();
}

public class TestAnonymousClass {
    public static Programmer programmer = new Programmer() {
        @Override
        public void develop() {
            System.out.println("我是在类中实现了接口的匿名内部类");
        }
    };

    public static void main(String[] args) {
        Programmer anotherProgrammer = new Programmer() {
            @Override
            public void develop() {
                System.out.println("我是在方法中实现了接口的匿名内部类");
            }
        };

        TestAnonymousClass.programmer.develop();
        anotherProgrammer.develop();
    }
}

As can be seen from the above example, anonymous classes can be created either in classes or in methods.
Earlier we also mentioned that anonymous classes can either inherit a concrete class or abstract class, or implement an interface. So in the above code, I created an interface called Programmer, and implemented the interface in the TestAnonymousClass class and the main() method respectively.
In addition to the interface, the Programmer can be either an abstract class or a concrete class.
Abstract class, like the following code:

public abstract class Programmer {
    public abstract void develop();
}

The specific class code is as follows:

public class Programmer {
    public void develop() {
        System.out.println("我是一个具体类");
    }
}

OK, go further, then what if there is no parameterless constructor for the Programmer class? Can we access class variables in anonymous classes? If we inherit a class, do we need to implement all methods in the anonymous class?

public class Programmer {
    protected int age;

    public Programmer(int age) {
        this.age = age;
    }

    public void showAge() {
        System.out.println("年龄:" + age);
    }

    public void develop() {
        System.out.println("开发中……除了异性,他人勿扰");
    }

    public static void main(String[] args) {
        Programmer programmer = new Programmer(38) {
            @Override
            public void showAge() {
                System.out.println("在匿名类中的showAge方法:" + age);
            }
        };
        programmer.showAge();
    }
}

1. When constructing an anonymous class, we can use any constructor. In the above code, we can see that we have used a constructor with parameters.
2. Anonymous classes can inherit concrete or abstract classes, and can also implement interfaces. So the access modifier rules are the same as those of ordinary classes. The child class can access the protected restricted properties in the parent class, but cannot access the private restricted properties.
3. If the anonymous class inherits a concrete class, such as the Programmer class in the above code, then it is not necessary to rewrite all methods. But if an anonymous class inherits an abstract class or implements an interface, then the anonymous class must implement all abstract methods that are not implemented.
4. You cannot use static initialization in an anonymous inner class, nor can you add static variables.
5. An anonymous inner class can have static constants modified by final.

Typical usage scenarios of anonymous classes

Temporary use: We sometimes need to add temporary implementations of some classes to fix some problems or add some functions. In order to avoid adding java files to the project, especially when using this class only once, we will use anonymous classes.
UI Event Listeners: In java graphical interface programming, the most commonly used scenario for anonymous classes is to create an event listener. For example:
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
}
}); In the
above code, we have implemented the setOnClickListener interface through an anonymous class. When the user clicks the button, it will trigger us The implemented onClick method.

Multithreading

Multithreading in Java is the use of multiple threads to complete the running process of a large task. Using multithreading can maximize the use of the CPU.
The use of multi-threading uses threads instead of processes to do task processing because threads are lighter than processes. Threads are a lightweight process, the smallest unit of program execution, and the main memory is shared between threads , And the process is not.

Thread life cycle

what?  Heard of these four concepts, many Java veterans have no idea!

As shown in the figure above, there are six states in the thread life cycle. We will now introduce these states in turn.
1. New: When we construct a thread instance, the thread has the New state. This state is the first state of the thread. At this point, the thread is not ready to run.
2. Runnable: When the start() method of the thread class is called, the thread will transition from the New state to the Runnable state. This means that this thread is ready to run. However, if the thread really wants to run, it needs a thread scheduler to schedule the execution of this thread. However, the thread scheduler may be busy executing other threads and cannot schedule the execution of this thread in time. The thread scheduler is based on the FIFO strategy to pick out a thread from the thread pool for execution.
3. Blocked: The thread may automatically switch to the Blocked state due to different situations. For example, waiting for I/O operations, waiting for network connections, and so on. In addition, any thread with a higher priority than the currently running thread may cause the running thread to turn to the Blocked state.
4. Waiting: Call the wait method of the synchronized object in the synchronization block, and the current thread will enter the Waiting state. If notify()/notifyAll() is called in a synchronized block where the same object in another thread is synchronized, it may cause the Waiting thread to enter the Runnable state.
5.Timed_Waiting: Same as Waiting state, but there will be a time limit. When the timeout expires, the thread will automatically enter the Runnable state.
6. Terminated: The thread will enter the Terminated state after the thread's run() method is executed or after the run() method exits abnormally.

Why use multithreading

In the vernacular, it is to use multiple threads to do multiple things at the same time to make Java applications run faster, using threads to implement parallelism and concurrency. Today's CPUs are multi-core and have a high frequency. If a single thread is used, the advantages of multi-core CPUs are not fully utilized.
Important advantage

  • Can make better use of CPU
  • Can better improve user experience related to responsiveness
  • Can reduce response time
  • Can serve multiple clients at the same time

    There are two ways to create threads

1. Create a thread by inheriting the Thread class.
This inherited class will override the run() method of the Thread class. The actual running of a thread starts from within the run() method, and the run() method of this thread is called through the start() method.


public class MultithreadDemo extends Thread {
    @Override
    public void run() {
        try {
            System.out.println("线程 " +  Thread.currentThread().getName() + " 现在正在运行");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            MultithreadDemo multithreadDemo = new MultithreadDemo();
            multithreadDemo.start();
        }
    }
}

2. Create a thread by implementing the Runnable interface.
We create a new class that implements the java.lang.Runnable interface and implement its run() method. Then we will instantiate a Thread object and call the start() method of this object.


public class MultithreadDemo implements Runnable {

    @Override
    public void run() {
        try {
            System.out.println("线程 " + Thread.currentThread().getName() + " 现在正在运行");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(new MultithreadDemo());
            thread.start();
        }
    }
}

Comparison of two creation methods

  • If a class inherits the Thread class, then this class cannot inherit any other classes. Because Java is single inheritance, it is not allowed to inherit multiple classes at the same time. Multiple inheritance can only use interfaces, and a class can implement multiple interfaces. Therefore, using the Runnable interface is better in practice than inheriting the Thread class.
  • The first method of creation, you can override yield(), interrupt() and other methods that may not be commonly used. But if we use the second method to create threads, methods such as yield() cannot be rewritten.

    Synchronize

Synchronization is meaningful only under multi-threaded conditions, and only one thread can execute a synchronized block at a time.
In Java, the concept of synchronization is very important, because Java itself is a multi-threaded language. In a multi-threaded environment, proper synchronization is extremely important.

Why use synchronization

To execute code in a multithreaded environment, if an object can be accessed by multiple threads, it is very necessary to use synchronization for this object in order to avoid errors in the object state or program execution.
Before we dive into the concept of synchronization, let's take a look at synchronization-related issues.

class Production {

    //没有做方法同步
    void printProduction(int n) {
        for (int i = 1; i <= 5; i++) {
            System.out.print(n * i+" ");
            try {
                Thread.sleep(400);
            } catch (Exception e) {
                System.out.println(e);
            }
        }

    }
}

class MyThread1 extends Thread {

    Production p;

    MyThread1(Production p) {
        this.p = p;
    }

    public void run() {
        p.printProduction(5);
    }

}

class MyThread2 extends Thread {

    Production p;

    MyThread2(Production p) {
        this.p = p;
    }

    public void run() {
        p.printProduction(100);
    }
}

public class SynchronizationTest {
    public static void main(String args[]) {
        Production obj = new Production(); //多线程共享同一个对象
        MyThread1 t1 = new MyThread1(obj);
        MyThread2 t2 = new MyThread2(obj);
        t1.start();
        t2.start();
    }
}

After running the above code, since we did not add synchronization, we can see that the running result is very confusing.
Output: 100 5 10 200 15 300 20 400 25 500
Next, we add synchronization to the printProduction method:

class Production {

    //做了方法同步
    synchronized void printProduction(int n) {
        for (int i = 1; i <= 5; i++) {
            System.out.print(n * i+" ");
            try {
                Thread.sleep(400);
            } catch (Exception e) {
                System.out.println(e);
            }
        }

    }
}

When we add synchronization to printProduction(), if there is already a thread executing, there will be no thread that can execute this method again. This time, the output result after synchronization is added in order.
Output: 5 10 15 20 25 100 200 300 400 500
Similar to synchronizing methods, you can also synchronize Java classes and objects.
Note: In fact, sometimes we don't have to synchronize the entire method. For performance reasons, we can actually synchronize only the part of the code in the method that we need to synchronize. The part of the code that is synchronized is the synchronization block in the method.

Serialization

Java serialization is a mechanism for converting a Java object into a byte stream. Converting from the byte stream back to the Java object is called deserialization, which is the reverse operation of serialization.
Serialization and deserialization are platform-independent, that is to say you can serialize on Linux system and then deserialize on Windows operating system.
If you want to serialize an object, you need to use the writeObject() method of the ObjectOutputStream class. If you want to deserialize, you must use the readObject() method of the ObjectOutputStream class.
As shown in the figure below, the objects are converted into byte streams and stored in different media. This process is serialization. On the right side of the figure, you can also see that the byte stream is obtained from different media, such as memory, and converted into objects. This is called deserialization.
what?  Heard of these four concepts, many Java veterans have no idea!

Why use serialization

If we create a Java object, the state of this object will disappear after the program is executed or exited, and will not be saved.
Therefore, in order to solve this type of problem, Java provides a serialization mechanism. In this way, we can temporarily store or persist the state of the object, so that when we need this object later, we can restore the object through deserialization.
Here are some codes to see how we do serialization.

import java.io.Serializable;

public class Player implements Serializable {

    private static final long serialVersionUID = 1L;

    private String serializeValueName;
    private transient String nonSerializeValuePos;

    public String getSerializeValueName() {
        return serializeValueName;
    }

    public void setSerializeValueName(String serializeValueName) {
        this.serializeValueName = serializeValueName;
    }

    public String getNonSerializeValueSalary() {
        return nonSerializeValuePos;
    }

    public void setNonSerializeValuePos(String nonSerializeValuePos) {
        this.nonSerializeValuePos = nonSerializeValuePos;
    }

    @Override
    public String toString() {
        return "Player [serializeValueName=" + serializeValueName + "]";
    }
}
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class SerializingObject {
    public static void main(String[] args) {

        Player playerOutput = null;
        FileOutputStream fos = null;
        ObjectOutputStream oos = null;

        playerOutput = new Player();
        playerOutput.setSerializeValueName("niubi");
        playerOutput.setNonSerializeValuePos("x:1000,y:1000");

        try {
            fos = new FileOutputStream("Player.ser");
            oos = new ObjectOutputStream(fos);
            oos.writeObject(playerOutput);

            System.out.println("序列化数据被存放至Player.ser文件");

            oos.close();
            fos.close();

        } catch (IOException e) {

            e.printStackTrace();
        }
    }
}

Output: The serialized data is stored in the Player.ser file

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class DeSerializingObject {

    public static void main(String[] args) {

        Player playerInput = null;
        FileInputStream fis = null;
        ObjectInputStream ois = null;

        try {
            fis = new FileInputStream("Player.ser");
            ois = new ObjectInputStream(fis);
            playerInput = (Player) ois.readObject();

            System.out.println("从Player.ser文件中恢复");

            ois.close();
            fis.close();

        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }

        System.out.println("player名字为 : " + playerInput.getSerializeValueName());
        System.out.println("player位置为 : " + playerInput.getNonSerializeValuePos());
    }
}

Output:

从Player.ser文件中恢复
player名字为 : niubi
player位置为 : null

Key features

1. If the parent class implements the Serializable interface, then the subclass does not need to implement the Serializable interface. But the reverse will not work.
2. Serialization only supports non-static member variables
3. Static modified variables and constants and transient modified variables will not be serialized. So, if we don't want to serialize some non-static member variables, just use transient to modify them.
4. When deserializing an object, the object's constructor will not be called.
5. If an object is referenced by an object to be serialized, the object will also be serialized, and the object must also implement the Serializable interface.

to sum up

First, we introduced the definition, usage scenarios and usage methods of anonymous classes.
Secondly, we discussed multi-threading and its life cycle as well as the usage scenarios of multi-threading.
Once again, we understand synchronization. After knowing synchronization, only one thread is allowed to execute the synchronized method or code block at the same time. When a thread is executing synchronized code, other threads can only wait in the queue until the thread executing the synchronized code releases resources.
Finally, we know that serialization is to store the state of an object for subsequent use.

what?  Heard of these four concepts, many Java veterans have no idea!

Guess you like

Origin blog.51cto.com/15006939/2551691