Today’s topic is about job hunting, which is something that every technical person has to go through many times in their career. For most of us, there is a lot of preparation before entering the company of our choice, and a thorough interview question will help us avoid a lot of trouble. Before job-hopping season comes, I specially do this series of articles, on the one hand to help myself to consolidate the foundation, on the other hand, I also hope to help friends who want to change jobs.
If you want to learn about distributed, microservices, JVM, multithreading, architecture, Java, python, don’t scan the code, or you will suffer the consequences
Related concepts Three characteristics of object orientation encapsulation, inheritance, polymorphism, this should be well-known, sometimes with abstraction.
The benefits of polymorphism allow different classes of objects to respond to the same message, that is, the same message can behave in many different ways depending on the sending object (sending a message is a function call). The main advantages are as follows:
Replaceable: Polymorphism is replaceable for existing code
Extensibility: Adding new subclasses does not affect the existing class structure
Interface: Polymorphism is implemented by a superclass that provides a common interface to subclasses through method signatures, which subclasses can refine or override.
flexibility
Simplify the sex
How to implement polymorphism in code There are three main ways to implement polymorphism:
- Interface implementation
- Inherits the parent overriding method
- Method overloading in the same class
Virtual machine is how to implement polymorphic Dynamic binding technology. During the execution, the actual type of the referenced object is determined and the corresponding method is called according to the actual type.
The meaning of an interface can be summed up in three words: specification, extension, and callback.
The meaning of Abstract Classes The meaning of abstract classes can be summed up in three sentences:
Provide a common type for other subclasses
Encapsulate content that is repeatedly defined in subclasses
Define abstract methods. Subclasses have different implementations but are defined consistently
Comparison between Interfaces and Abstract Classes Abstract Classes interface Default methods Abstract classes can have default methods implemented before Java 8, the implementation of methods did not exist in interfaces. Implementation Subclasses inherit abstract classes using the extends keyword. If the subclass is not abstract, the subclass needs to provide an implementation of the methods declared in the abstract class. Subclasses implement interfaces using implements and need to provide implementations of all declarations in the interface. Constructor Abstract classes can have constructors, You can’t distinguish it from a normal class in an interface. An abstract class can’t be instantiated. An interface is a completely different type A subclass can have multiple interfaces add a new method If you want to add a new method to an abstract class, you can provide a default implementation, so you don’t have to modify the existing code of the subclass if you add a new method to the interface, you need to implement that method in the subclass.
Whether a static method of a parent class can be overridden by a child class cannot. Overrides only apply to instance methods, not static methods, and subclasses that have the same signature as their parent class are called hidden.
What is an immutable object? An immutable object means that once an object has been created, its state cannot be changed. Any changes create a new object, such as String, Integer, and other wrapper classes.
What’s the difference between a static variable and an instance variable? Static variables are stored in the method area and are class-owned. Instance variables are stored in the heap and their references are stored in the current thread stack.
Can I create an immutable object that contains a mutable object? It is certainly possible to create an immutable object that contains a mutable object. You just need to be careful not to share references to mutable objects and return a copy of the original object if changes are needed. The most common example is when an object contains a reference to a date object.
Java uses new in several ways to create objects
By reflection
The clone
Through serialization mechanism
The first two need to explicitly call the constructor. The one that causes the most coupling happens to be the first, so you’ll find that any framework that involves decoupling has to reduce the use of new first.
Before IDK 1.7, the Switch supported only byte, short, CHAR, int or their corresponding encapsulated classes and Enum types. Since IDK 1.7, the Switch has supported String.
Can switch work on Byte and long? It can be used with byte, but not with long.
String s1= “ab”, String s2= “a” + “b”, String s3= “a”, String s4= “b”, s5=s3+ S4 Returns false. S5 =new String(” ab “); s2 =new String(” ab “);
Are you familiar with the String intern()? The intern() method first looks for the presence of the constant value in the constant pool, creates it if it doesn’t exist, and returns it if it does. Such as String s1 = “aa”; String s2=s1.intern(); System.out.print(s1==s2); / / return true
What are the public methods in Object? equals()
clone()
getClass()
notify(),notifyAll(),wait()
toString
There are four types of references in Java: strong, soft, weak, and virtual. The different reference types are mainly reflected in GC:
Strong references: If an object has strong references, it will not be collected by the garbage collector. Even if the current memory space is insufficient, the JVM does not reclaim it, but instead throws an OutOfMemoryError, causing the program to abort abnormally. If you want to break the association between a strong reference and an object, you can explicitly assign the reference to NULL so that the JVM can reclaim the object at the appropriate time.
Soft references: When a soft reference is used, if there is enough memory, the soft reference can continue to be used without being collected by the garbage collector, and only when there is insufficient memory, the soft reference is collected by the garbage collector.
Weak references: Objects with weak references have a shorter lifetime. Because when the JVM does garbage collection, weak references are collected whenever they are found, regardless of whether there is currently sufficient memory space. However, because the garbage collector is a low-priority thread, it is not always possible to find weak reference objects quickly.
Virtual references: As the name implies, virtual references. If an object holds only virtual references, it has no references and can be collected by the garbage collector at any time.
See In Depth Object References for more information:
Blog.csdn.net/dd864140130…
What is the difference between WeakReference and SoftReference? This is explained in the four reference types, but it can be explained briefly here: Although WeakReference and SoftReference are both beneficial to improving the efficiency of GC and memory, WeakReference will be recovered by GC once it loses the last strong reference, while SoftReference cannot prevent collection. But it can be deferred until the JVM runs out of memory.
Unlike C, where we can control the allocation and release of memory, in Java we sometimes need to control when objects are reclaimed, so there are different reference types, which can be said to be an uncontrollable compromise on the timing of GC collection. The following usage scenarios can be fully illustrated:
Soft and Weak References solve OOM problems: Use a HashMap to store the mapping between the path of the image and the soft references associated with the corresponding image object. When memory runs out, the JVM automatically reclaims the space occupied by these cached image objects, effectively avoiding OOM problems.
Caching Java objects through soft references: For example, if we create a Person class, if we need to rebuild an instance every time we need to query a Person’s information, even if it has been queried only a few seconds before, this will consume a lot of Person objects, and because these objects have a relatively short life cycle, Multiple GCS can be caused affecting performance. At this point, a combination of soft references and HashMap can be used to build a cache to provide performance.
The difference between == and eqauls() in Java, between equals() and hashcode == is the operator that compares whether two variables are equal, and equals is the method of the Object class that compares whether two objects are equal. The default equals method of the Object class compares the addresses of two objects with the same result as ==. In other words: primitive types compare with ==, comparing their values. By default, when objects are compared with ==, they compare memory addresses. If you want to compare object contents, you need to override the equal method.
Hashcode () is a method of the Object class that returns a hash value. If two objects are equal according to the equal() method, then calling the hashCode() method on either object must produce the same hash value. If two objects are not equal according to the eqaul() method, the resulting hash values are not necessarily equal (and will be equal in the case of collisions).
What does a.hash code () do? The hashCode() method is the hash value of the corresponding object’s integer. It is commonly used for hash-based collection classes such as Hashtable, HashMap, LinkedHashMap, and so on. It is particularly closely related to the equals() method. According to the Java specification, using the equal() method to determine that two objects are equal must have the same Hashcode.
When an object is put into a collection, it first checks whether the hashcode to be put into the object already exists in the collection. If not, it is put into the collection directly. If hashCode is equal, then the equal() method determines whether the object to be put into is equal to any object in the collection: if equal() determines not equal, the element is put directly into the collection, otherwise not.
Is it possible that two objects that are not equal might have the same Hashcode? Yes, two objects that are not equal might have the same HashCode value, and that’s why there are conflicts in a Hashmap. If two objects are equal, they must have the same hashcode value, not vice versa.
Can I use random numbers in HashCode? No, because the hashCode values for the same object must be the same
If a and b are both objects, then a==b is a reference to compare two objects, and returns true only if a and B refer to the same object in the heap, while a.equals(b) is a logical comparison. This method is often overridden to provide logically consistent comparisons. For example, the String class overrides equals() so it can be used to compare two different objects that contain the same letters.
3*0.1==0.3 what is the return value false, because some floating point numbers cannot be represented exactly.
Is there any difference between a=a+b and a+=b? The += operator implicitly casts the result type of the addition operation to the type that holds the result, whereas a=a+b does not. Byte a = 127; byte b = 127; b = a + b; // error : cannot convert from int to byte b += a; A +b raises a and B to int, so assigning an int to byte causes a compilation error.
short s1= 1; s1 = s1 + 1; Is there anything wrong with this code? If so, how to fix it? Error: short is automatically promoted to int (s1+1 is int)
short s1= 1; s1 += 1; Is there anything wrong with this code? If so, how to fix it? The += operator automatically forces the result of the right-hand expression to match the left-hand data type, so yes.
The difference between am& and am& is to remember that am& is a bitwise operation, while am& is a logical operator. Also remember that logical operators have short-circuiting properties, and & does not.
public class Test{ static String name;
public static void main(String[] args){ if(name! =null&userName.equals(“”)){ System.out.println(“ok”); }else{ System.out.println(“erro”); }}}
The above code will throw a null pointer exception.
Can a Java file have classes inside it? (Non-inner class) can have only one public public class, but can have multiple classes decorated with default.
How to exit a multi-layer nested loop correctly? Use a label and break;
By adding an identifier to the outer loop
The role of inner classes An inner class can have multiple instances, each with its own state information and independent of the information of other peripheral objects. Within a single enclosing class, you can have multiple inner classes implement the same interface in different ways, or inherit from the same class. The moment the inner class object is created does not depend on the creation of the outer class object. The inner class doesn’t have the puzzling is-A system, it’s like a separate entity.
The inner class provides better encapsulation and is not accessible by any other class except the enclosing class.
Final is a modifier that can modify variables, methods, and classes. If final decorates a variable, it means that its value cannot be changed after initialization. Finalize method is a method called before objects are collected to give objects themselves the last chance to revive, but there is no guarantee when To call Finalize. Finally is a keyword that is used with try and catch for exception handling. A finally block must be executed regardless of whether an exception occurs in the try block.
Clone () is a method of which class? Java.lang.Cloneable is an explicit interface that does not contain any methods. The Clone method is defined in the Object class. You also need to know that the Clone () method is a native method, which means it is implemented in C or C ++ or another native language.
What is the difference between a deep copy and a shallow copy? Shallow copy: All variables of the copied object have the same values as the original object, and all references to other objects still refer to the original object. In other words, shallow copy copies only the object in question, not the object it references.
Deep copy: All variables of the copied object have the same values as the original object, and variables that refer to other objects refer to the copied object instead of the original referenced objects. In other words, the deep copy copies all the objects referenced by the object to be copied.
What are the uses of static? Almost everyone knows the two basic uses of the static keyword: static variables and static methods. Static variables/methods are static resources of the class that are shared by the class instance.
In addition to static variables and static methods, static is also used for static blocks, mostly for initialization operations:
Public calss PreCache{static{// PreCache}}
Static is also used to modify inner classes, which are called static inner classes.
Import static is a new feature introduced after JDK 1.5 that can be used to specify the static resources to be imported into a class without using the class name. Resource name. You can use the resource name directly, for example:
import static java.lang.Math.*;
public class Test{
public static void main(String[] args){ //System.out.println(Math.sin(20)); System.out.println(sin(20)); }}
“Final” is also a popular question in many interviews. It is good to have three answers: 1. Classes modified by final cannot be inherited. 2. Methods modified by final cannot be overridden. 3. Variables modified by final cannot be changed. If you decorate a reference, then the reference is immutable and what the reference points to is mutable. 4. Methods modified by final are attempted by the JVM to be inlined to improve performance 5. Constants modified by final are stored in the constant pool at compile time.
It is better to answer the two reordering rules that the compiler follows for final fields: 1. There is no reordering between a write to a final field within a constructor and a subsequent assignment of a reference to the constructed object to a reference variable. 2. There is no reordering between the first reading of a reference to an object containing a final field and the subsequent first reading of the final field.
How many bytes are int char,long in Java? Short 2 16 int 4 32 long 8 64 float 4 32 Double 8 64 char 2 16
What is the length of an int in a 64-bit JVM? In Java, the length of a variable of type int is a fixed value of 32 bits, regardless of the platform. In 32-bit and 64-bit Java virtual machines, the length of an int is the same.
Difference between int and Integer Integer is the packaging type of an int, which is automatically converted during unpacking and packing. Int is a primitive type that holds values directly, while INTEGER is an object that is referred to by a reference.
Who takes up more memory, int or Integer? Integer objects take up more memory. Integer is an object whose metadata needs to be stored. But int is a primitive type of data, so it takes up less space.
The difference between String, StringBuffer, and StringBuilder is that String is a String constant and final. StringBuilder String variable (thread unsafe).
The main difference between a String and a StringBuffer is performance: A String is immutable, and every operation on a String creates a new String and points to the new String. So try not to do a lot of concatenation of strings, otherwise you will have a lot of temporary objects, causing the GC to start working and affecting system performance.
StringBuffer operates on the object itself, rather than generating new objects, so we recommend using StringBuffer in cases where there is a lot of concatenation.
But note that the JVM now optimizes String concatenation: String s= “This is only” + “simple” + “test” is optimized to String S = “This is only simple test” by the VM.
A StringBuffer is a thread-safe mutable string whose internal implementation is a mutable array. StringBuilder was added to JDK 1.5 and is similar to StringBuffer, but not thread-safe. Therefore, using StringBuilder provides better performance without multithreading issues.
What are compiler constants? What are the risks of using it? Public static final variables are compile-time constants, which are optional. These variables are actually replaced at compile time because the compiler knows their values and knows that they cannot be changed at run time. One problem with this approach is that you use a public compile-time constant from an internal or third-party library, but the value is later changed by someone else, but your client still uses the old value, even if you have deployed a new JAR. To avoid this, be sure to recompile your program when updating dependent JAR files.
What type of price is good in Java? Use BigDecimal if you are not particularly concerned with memory and performance, otherwise use a double of predefined precision.
You can convert a byte to a String using the constructor that accepts the byte[] argument. The important thing is to use the correct encoding, otherwise the platform default encoding will be used, which may or may not be the same as the original encoding.
Can int be forcibly converted to byte? What problems will arise? We can cast, but ints are 32 bits and byte is 8 bits in Java, so if we cast the higher 24 bits of ints, byte ranges from -128 to 128 will be discarded
What garbage collection algorithms do you know about garbage collection? Garbage collection is easy to understand in theory. There are several specific methods:
- Mark-clear
- Mark-copy
- Mark-tidy
- For more details on generational collection, see the in-depth understanding of garbage collection algorithms:
Blog.csdn.net/dd864140130…
How to determine whether an object should be reclaimed this is the so-called object viability judgment, commonly used in two ways: 1. Reference counting method; 2. Object accessibility analysis. Due to the cross-reference problem with reference counting methods, object reachability analysis algorithms are commonly used by JVM VMS today.
Garbage collection The most basic method of Java garbage collection is generational collection. Regions in memory are divided into different generations, and objects are stored in regions of the corresponding generation according to how long they live. A typical implementation is divided into three generations: young, old, and permanent. Memory allocation occurs in the younger generation. When an object survives long enough, it is copied into the old generation. Different garbage collection algorithms can be used for different generations. The starting point of generation division is the statistical rule derived from the study of the life time of the object in application. In general, most objects in an application have a short lifetime. For example, local variables live only during the execution of the method. With this in mind, garbage collection algorithms can be tailored to the younger generation.
What happens when system.gc () is called? The GC is told to start work, but the time when the GC actually starts is uncertain.
In short, a process is the basic unit of execution and resource allocation. Each program has at least one process, and each process has at least one thread. A process has a separate memory unit during execution, while multiple threads share memory resources, reducing the number of switches and making it more efficient. A thread is an entity of a process. It is the basic unit of CPU scheduling and dispatching. It is a basic unit smaller than a program that can run independently. Multiple threads in the same process can execute concurrently.
Do you know anything about daemons? What’s the difference between it and a non-daemon thread? The JVM waits for the non-daemon thread to complete and shut down, but it doesn’t wait for the daemon thread. The most typical example of a daemon thread is a GC thread.
Multithreaded context switching is the process of switching CPU control from one running thread to another thread that is ready and waiting for CPU execution.
How to create two kinds of threads? What’s the difference? By implementing java.lang.Runnable or by extending the java.lang.Thread class. Implementing the Runnable interface is probably better than extending Thread. There are two reasons:
Java does not support multiple inheritance. Therefore, extending Thread means that the subclass cannot extend other classes. A class that implements the Runnable interface may extend another class.
Classes might just be required to be executable, so inheriting the entire Thread class would be too expensive.
What is the difference between the start() and run() methods in Thread? The start() method is used to start the newly created thread, and the run() method is called inside start(), which does not have the same effect as calling run() directly. When you call the run() method, it will only be called in the original thread. No new thread will be started, so the start() method will start a new thread.
The Thread class provides a holdsLock(Object obj) method that returns true if and only if the Object obj’s monitor is held by a Thread. Note that this is static, meaning that “Thread” refers to the current Thread.
The Runnable interface’s run() method returns void, and all it does is execute the code in the run() method; The Call () method in the Callable interface, which returns a value, is a generic type that can be used in conjunction with Future and FutureTask to retrieve the result of asynchronous execution. And this is actually a very useful feature, because one of the big reasons that multithreading is more difficult and more complex than single threading is because multithreading is so unpredictable. Does a thread execute? How long did a thread execute? Is the expected data already assigned when a thread executes? We don’t know. All we can do is wait for the multithreaded task to finish. Callable+Future/FutureTask, on the other hand, can easily obtain the results of multithreading, and can cancel the task if the waiting time is too long to obtain the required data.
Blocking is the process of suspending the execution of a thread until a condition (such as a resource is ready) occurs. Those of you who have studied operating systems will be familiar with it. Java provides a number of ways to support blocking, so let’s take a look at each one.
Sleep () Allows you to specify a period of time in milliseconds. Sleep () causes the thread to block for a specified period of time and not get CPU time. After the specified time, the thread returns to the executable state. Typically, sleep() is used to wait for a resource to be ready: Suspend () and resume() are used together. Suspend () causes a thread to enter a blocked state and does not resume automatically until its corresponding resume() is called. To get the thread back into an executable state. Typically, suspend() and resume() are used to wait for a result from another thread: after a test finds that the result has not yet been produced, suspend the thread, and resume() is called after another thread has produced the result. Yield () Yield () causes the current thread to give up the CPU time it is currently allocated, but does not cause the current thread to block, that is, the thread is still in an executable state and may be allocated CPU time again at any time. The effect of invoking yield() is equivalent to the scheduler deciding that the thread has executed enough time to switch to another thread. Wait () and notify() are used together. Wait () causes a thread to block. When notify() is called or when the specified time has elapsed, the thread must be called again.
The differences between wait(),notify(), and suspend() and resume() may at first appear to be no different from the suspend() and resume() methods, but in fact they are very different. The crux of the difference is that none of the methods described above will release the locked lock (if any) when blocking, as opposed to the other way around. The core differences above lead to a series of detailed differences.
First, all of the methods described above belong to the Thread class, but this pair belongs directly to the Object class, which means that all objects have this pair of methods. This may seem strange at first, but it is actually quite natural because the pair of methods that block release the lock that is held by any object, and calling wait() on any object causes the thread to block and the lock on that object to be released. Calling the notify() method on any object results in unblocking (but not actually executing until the lock is acquired) from one of the randomly selected threads that blocked by calling the wait() method on that object.
Second, all of the methods described above can be called from anywhere, but this pair of methods must be called from a synchronized method or block for the simple reason that it is only in a synchronized method or block that the current thread owns the lock and can release it. Similarly, the lock on the object calling this pair of methods must be owned by the current thread in order for any lock to be released. Therefore, the pair of method calls must be placed in such a synchronized method or block, whose locking object is the object calling the pair of methods. If they do not meet the conditions, the program, though still able to compile, but abnormal IllegalMonitorStateException at run time.
Wait () and notify() are often used with the synchronized keyword because of these properties, and a comparison between them and the operating system interprocess communication mechanism reveals their similarities: Synchronized methods, or blocks, provide functionality similar to operating system primitives in that they execute without interference from multithreading, which is equivalent to block and wakeup primitives (both declared synchronized). Their combination enables us to implement a series of sophisticated inter-process communication algorithms (such as semaphore algorithms) on operating systems and to solve various complex inter-thread communication problems.
Wait () and notify() methods The threads that are unblocked by calling notify() are randomly selected from threads that are blocked by calling wait() on this object. It is impossible to predict which threads will be selected, so take special care in programming to avoid problems caused by this uncertainty.
There is a notifyAll() method that performs a similar function. The only difference is that a notifyAll() method unblocks all threads that are blocked by calling the wait() method. Of course, only the thread that acquired the lock can enter the executable state.
You can’t talk about blocking without talking about deadlocks, and a quick analysis shows that deadlocks can occur from calls to both the suspend() method and to wait() methods with no timeout period specified. Unfortunately, Java does not support deadlock avoidance at the language level, and we must be careful to avoid deadlocks in programming.
We’ve looked at the various methods for implementing thread blocking in Java, focusing on wait() and notify() because they are the most powerful and flexible to use, but this makes them less efficient and error-prone. In practice, we should use various methods flexibly in order to better achieve our goals.
Conditions for deadlock 1. Mutually exclusive condition: A resource can be used by only one process at a time. 2. Request and hold conditions: when a process is blocked by requesting resources, it holds on to acquired resources. 3. Non-deprivation condition: the process can not forcibly deprive the resources it has acquired before they are used up. 4. Circular waiting condition: a circular waiting resource relationship is formed between several processes.
Why should wait() and notify()/notifyAll() be called in a synchronized block? This is mandatory by the JDK. Wait () and notify()/notifyAll() must acquire the lock of an object before being called
What are the differences between wait() and notify()/notifyAll() when object monitors are abandoned? The differences between Wait () and notify()/notifyAll() are as follows: Wait () releases the object monitor immediately, and notify()/notifyAll() waits for the rest of the thread code to execute before giving up the object monitor.
Wait () vs. sleep() The difference between wait() and sleep() has been explained in detail above, so here’s a summary:
Sleep () comes from Thread, and wait() comes from Object. The thread does not release the object lock during the call to sleep(). Calling the wait thread releases the object lock
Sleep () does not allocate system resources after sleep, and wait allows other threads to occupy the CPU
Sleep (milliseconds) specifies how long it takes to sleep, and it wakes up automatically. Wait () is used with notify() or notifyAll()
One obvious reason why wait, Nofity, and nofityAll are not in the Thread class is that JAVA provides object-level locks rather than thread-level locks. Each object has a lock, which is acquired by the Thread. It makes sense to call wait() on an object if the thread needs to wait for some lock. If the wait() method is defined in the Thread class, it is not obvious which lock the Thread is waiting on. Simply put, because wait, notify, and notifyAll are lock-level operations, we define them in the Object class because locks belong to objects.
If a thread is blocking because it called wait(), sleep(), or join(), you can interrupt it and wake it up by throwing InterruptedException. If the thread encounters AN IO block, there is nothing to be done, because IO is implemented by the operating system, and Java code has no direct access to the operating system.
Context switching in multiple threads is the process of switching CPU control from one thread that is already running to another thread that is ready and waiting for CPU execution.
Synchronized is the same keywords as if, else, for, and while. ReentrantLock is a class. Since ReentrantLock is a class, it provides more flexible features than synchronized. It can be inherited, can have methods, and can have a variety of class variables. ReentrantLock has more extensibility than synchronized in several aspects: (1) ReentrantLock can set the waiting time for acquiring locks, so as to avoid deadlocks. (2) ReentrantLock can obtain various locks information. (3) ReentrantLock can flexibly implement multi-way notification. Unsafe Lock (ReentrantLock) refers to the Unsafe park method, whereas synchronized refers to the Mark Word object header.
So what is a FutureTask and this is actually mentioned earlier, a FutureTask is a task for asynchronous computation. FutureTask can pass in a concrete implementation class of Callable, which can wait for the result of the asynchronous operation, determine whether the task has been completed, and cancel the task. Of course, since FutureTask is also an implementation class of the Runnable interface, it can also be put into a thread pool.
What if a thread has a runtime exception? If the exception is not caught, the thread stops executing. Another important point is that if this thread holds a monitor for an object, the object monitor is immediately released.
Spinlocks: spinlocks are enabled by default in JDK1.6. Based on previous observations, Shared data locked only lasts for a short period of time, for which a short period of time to suspend and resume the thread a bit wasteful, so here did a processing, the request to the thread lock in wait for a while, but don’t give up the processor execution time, look at the thread holding the lock can be quick release. In order for the thread to wait, it needs to perform a busy loop called a spin operation. After JDK6, adaptive spin locking was introduced, where the wait time was no longer fixed, but determined by the last spin time on the same lock and the state of the lock owner.
Biased locking: A lock optimization introduced after JDk1. to eliminate synchronization primitives for data in uncontested situations. Further improve the running performance of the program. Biased locks are biased, meaning that the lock is biased toward the first thread to acquire it. If the lock is not acquired by another thread during subsequent execution, the thread holding the biased lock will never need to synchronize again. Biased locking can improve the performance of a program with synchronization but no competition, that is to say, it is not always beneficial to the operation of the program. If most of the locks in the program are accessed by multiple different threads, then biased locking mode is redundant. On the premise of specific analysis, we can consider whether to use biased locking.
Lightweight lock: in order to reduce the performance cost of acquiring and releasing locks, “biased lock” and “lightweight lock” have been introduced, so there are four lock states in Java SE1.6: no lock state, biased lock state, lightweight lock state and heavyweight lock state, which will gradually upgrade with the competition situation. Locks can be upgraded but cannot be downgraded, meaning biased locks cannot be downgraded after being upgraded to lightweight locks.
Wait /notify/notifyAll, await/signal/signalAll For example, BlockingQueue is designed to share data between threads.
How to use wait() correctly? Use if or while? The wait() method should be called in a loop, because other conditions may not have been met by the time the thread gets to the start of CPU execution, so it is better to loop to check if the conditions have been met before processing. Here is a standard code that uses wait and notify:
synchronized (obj) { while (condition does not hold) obj.wait(); // (Releases lock, and reacquires on wakeup) … // Perform action appropriate to condition }
ThreadLocal variables are variables that are limited within a thread. They are owned by the thread itself and are not shared between multiple threads. Java provides a ThreadLocal class to support thread-local variables as a way to achieve thread-safety. However, be careful when using thread-local variables in a managed environment, such as a Web server, where the life of a worker thread is longer than the life of any application variable. Java applications run the risk of memory leaks if any thread-local variables are not released after work is done.
What does ThreadLoal do? Simple said ThreadLocal is a kind of to the practice of trading space for time in each Thread maintains a ThreadLocal. ThreadLocalMap isolating data, data is not Shared, nature is no Thread safety issues.
What is the role of the producer-consumer model? (1) The most important function of the producer-consumer model is to improve the operating efficiency of the whole system by balancing the production capacity of producers and the consumption capacity of consumers. (2) Decoupling, which is an incidental function of the producer-consumer model. Decoupling means that there is less connection between producers and consumers, and the less connection there is, the more they can develop independently without mutual restriction.
Writing a producer-consumer queue can be done either by blocking queues or by wait-notify.
Public class Producer implements Runnable{private final BlockingQueue implements Runnable;
public Producer(BlockingQueue q){ this.queue=q; }
@Override public void run() { try { while (true){ Thread.sleep(1000); Queue. Put (produce()); } }catch (InterruptedException e){
}
Copy the code
}
private int produce() { int n=new Random().nextInt(10000); System.out.println(“Thread:” + Thread.currentThread().getId() + ” produce:” + n); return n; }} public class Consumer implements Runnable {private final BlockingQueue;
public Consumer(BlockingQueue q){ this.queue=q; }
@Override public void run() { while (true){ try { Thread.sleep(2000); // Consume (queue.take()); }catch (InterruptedException e){
}}Copy the code
}
private void consume(Integer n) { System.out.println(“Thread:” + Thread.currentThread().getId() + ” consume:” + n);
}} public class Main {
public static void main(String[] args) { BlockingQueue queue=new ArrayBlockingQueue(100); Producer p=new Producer(queue); Consumer c1=new Consumer(queue); Consumer c2=new Consumer(queue);
new Thread(p).start();
new Thread(c1).start();
new Thread(c2).start();
Copy the code
}}
Using wait-notify is probably the most classic way to do this, so I won’t cover it here.
What happens if you submit a task and the thread pool queue is full? If you use LinkedBlockingQueue, which is an unbounded queue, it doesn’t matter, keep adding tasks to the blocking queue for execution, because LinkedBlockingQueue can be thought of as almost an infinite queue, Can store tasks indefinitely; If you’re using a bounded queue like ArrayBlockingQueue, the task is added to the ArrayBlockingQueue first, ArrayBlockingQueue is full, The RejectedExecutionHandler policy is used to handle the full task. The default policy is AbortPolicy.
Why use thread pools to avoid frequent thread creation and destruction and reuse of thread objects. In addition, using thread pools gives you the flexibility to control the number of concurrency depending on your project.
The thread scheduling algorithm used in Java is preemptive. After a thread runs out of CPU, the operating system calculates a total priority based on thread priority, thread hunger, etc., and allocates the next time slice to a particular thread.
Since Java uses a preemptive Thread scheduling algorithm, it is possible that one Thread often gains CPU control. In order to allow lower priority threads to gain CPU control, You can use Thread.sleep(0) to manually trigger an operating system allocation of time slices, which balances CPU control.
What is the CAS? CAS is called Compare and Swap. Suppose there are three operands: the memory value V, the old expected value A, and the value to be modified B. Change the memory value to B and return true if and only if the expected value A and the memory value V are the same, otherwise do nothing and return false. Of course, CAS must be volatile to ensure that the most recent value in main memory is retrieved each time. Otherwise, the old expected value, A, will remain the same for A thread and will never succeed as long as the CAS operation fails.
Optimistic locks: Optimistic locks assume that contention does not always occur, so it does not need to hold the lock. Compare and replace as an atomic operation to try to modify a variable in memory. Failure indicates a conflict, and retry logic should apply.
Pessimistic locks: Pessimistic locks assume that competition always occurs and therefore hold an exclusive lock every time they operate on a resource, just as synchronized does.
What is the concurrency of ConcurrentHashMap? ConcurrentHashMap concurrency is the size of the segment. The default value is 16, which means that up to 16 threads can operate on ConcurrentHashMap at the same time. This is ConcurrentHashMap’s biggest advantage over Hashtable. Can two threads fetch data from a Hashtable at the same time?
ConcurrentHashMap works differently in JDK 1.6 and JDK 1.8.
JDK 1.6: ConcurrentHashMap is thread-safe, but implemented in a different way than Hashtablea. A Hashtable locks the hash table structure and is blocking. When one thread holds the lock, other threads must block to wait for the lock to be released. ConcurrentHashMap is a split lock that does not lock the entire hash table, but a local lock. That is, a local lock that is held by one thread does not affect other threads’ access to other parts of the hash table. ConcurrentHashMap contains a Segment.
In JDK 8, ConcurrentHashMap uses an optimistic CAS algorithm instead of using Segment separation to implement synchronization, but the underlying implementation is “array + list -> red-black tree”.
CyclicBarrier and CountDownLatch The CyclicBarrier and CountDownLatch classes are very similar, both under java.util.concurrent and both can be used to indicate that the code is running at a point. The difference is that:
Once a thread of a CyclicBarrier reaches a certain point, the thread stops running and does not restart until all threads have reached this point. CountDownLatch is not the case. When a thread gets to a certain point, it just gives a value of -1 and the thread keeps running.
CyclicBarrier can only evoke one task, and CountDownLatch can evoke multiple tasks
CyclicBarrier is reusable, and CountDownLatch is not reusable. If the count is 0, the CountDownLatch is no longer available.
Is the ++ operator in Java thread safe? Not a thread-safe operation. It involves multiple instructions, such as reading variable values, incrementing them, and then storing them back into memory, which can have multiple threads crossing.
What are your best practices for multithreaded development? Naming a thread
Minimize synchronization range
Use volatile in preference
Use higher-level concurrency tools instead of wait and notify() for thread communication whenever possible, such as BlockingQueue,Semeaphore
Use concurrent containers in preference to synchronous containers.
Consider using thread pools
Can VOLATILE arrays be created for the volatile keyword? You can create volatile arrays in Java, but only a reference to the array, not the entire array. Changing the array to which the reference refers is protected by volatile, but not by volatile if multiple threads change the elements of the array simultaneously.
Can volatile make a nonatomic operation atomic? A typical example is having a member variable of type long in a class. If you know that the member variable will be accessed by multiple threads, such as counters, prices, etc., it is best to set it to volatile. Why is that? Because reading a long variable in Java is not atomic and requires two steps, if one thread is changing the value of the long variable, another thread may only see half of the value (the first 32 bits). But reading or writing to a volatile long or double is atomic.
One practice is to use volatile to modify long and double variables so that they can be read and written by atomic type. Double and long are both 64 bits wide, so reads of both types are split into two parts, first reading the first 32 bits and then reading the remaining 32 bits. This process is not atomic, In Java, however, volatile long or double variables are read and written atomically. Another use of volatile fixes is to provide memory barriers, as in distributed frameworks. In simple terms, the Java memory model inserts a write barrier before you write a volatile variable, and a read barrier before you read a volatile variable. This means that when you write a volatile field, you can ensure that any thread can see the value you write, and that any value changes are visible to all threads prior to writing, because the memory barrier updates all other written values to the cache.
What guarantees do volatile variables provide? Volatile serves two main purposes: instruction reordering avoidance and visibility assurance. For example, the JVM or JIT will reorder statements for better performance, but volatile variables will not be reordered with other statements even if they are assigned without synchronized blocks. Volatile provides a happens-before guarantee that changes made by one thread are visible to other threads. Volatile can also provide atomicity in some cases, such as reading 64-bit data types, such as long and double, which are not atomic (low 32 bits and high 32 bits), but double and long, which are volatile, are atomic.
Everyone should be familiar with the system of collection, especially the principle of List and Map, which we often use. Here we can just look at this picture:
More on the collection class summary:
Write.blog.csdn.net/postedit/40…
Poll () method and remove() method difference? Poll () and remove() both fetch an element from the queue, but poll() returns null on failure to fetch an element, and remove() throws an exception on failure.
A PriorityQueue is a PriorityQueue that ensures that the highest or lowest priority element is always at the head of the queue, but the LinkedHashMap maintains the order in which the elements were inserted. There is no guaranteed order when traversing a PriorityQueue, but the LinkedHashMap class guarantees that the traversal order is the order in which the elements were inserted.
What is the difference between a WeakHashMap and a HashMap? WeakHashMap works like a normal HashMap, but uses a weak reference as the key, meaning that the key/value is reclaimed when the key object has no reference.
What’s the difference between ArrayList and LinkedList? The most obvious difference is that the underlying data structure of ArrrayList is an array, which supports random access, while the underlying data structure of LinkedList is a two-way circular LinkedList, which does not support random access. Using subscripts to access an element, the time complexity of ArrayList is O(1) and LinkedList is O(n).
What’s the difference between ArrayList and Array? Array can hold primitive types and objects, whereas ArrayList can only hold objects.
Array is a specified size, whereas ArrayList is a fixed size
Default sizes for ArrayList and HashMap? In Java 7, the default size for ArrayList is 10 elements, and the default size for HashMap is 16 elements (which must be a power of 2). This is a snippet of the ArrayList and HashMap classes in Java 7.
private static final int DEFAULT_CAPACITY = 10;
//from HashMap.java JDK 7 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
What’s the difference between Comparator and Comparable? The Comparable interface is used to define the natural order of objects, while the Comparator is typically used to define user-customized orders. Comparable is always only one, but you can have more than one comparator to define the order of objects.
How to implement set sorting? You can use ordered Collections, such as TreeSet or TreeMap, or you can use ordered Collections, such as list, and sort through collections.sort ().
You can print Arrays using the arrays.tostring () and arrays.deepToString () methods. Because Arrays don’t implement toString(), passing Arrays to system.out.println () won’t print out the contents of the array, but arrays.tostring () will print each element.
Is the LinkedList one-way or two-way? Two-way circular list, specific implementation of their own access to the source code.
TreeMap is the realization principle of red black tree implementation, the specific implementation of their own access to the source code.
The key to this question is whether the interviewer uses the remove() method of ArrayList or Iterator. Here’s a sample code, is to use the right way to realize in the process of traversing remove elements, and won’t appear abnormal ConcurrentModificationException sample code.
What is a ArrayMap? How is it different from HashMap? ArrayMap is provided with the Android SDK and can be skipped by non-Android developers. ArrayMap uses two arrays to simulate a map, which takes up less memory and is more efficient. See this article: ArrayMap VS HashMap: lvable.com/?p=217]
Implementation principle of HashMap
- Overview of HashMap: HashMap is an asynchronous implementation of the Map interface based on hash tables. This implementation provides all optional mapping operations and allows null values and NULL keys. This class does not guarantee the order of the mapping, and in particular it does not guarantee that the order is constant.
- The data structure of HashMap: In the Java programming language, the most basic structure is two kinds, one is an array, the other is a mock pointer (reference), all data structures can be constructed with these two basic structures, HashMap is no exception. A HashMap is actually a “linked list hash” data structure, which is a combination of arrays and lists.
When we put an element into a Hashmap, we first recalculate the hash value based on the hashcode of the key. The hash value is calculated to the element’s location in the array (subscript). If the array already contains other elements at that location, the elements at that location are stored as a linked list, and the new elements are added in the header. The first one goes to the end of the chain. If there is no element at that location in the array, the element is placed directly at that location in the array.
In Jdk 1.8, the implementation of HashMap is optimized. When there are more than eight nodes in the list, the list will be converted to a red-black tree to improve query efficiency, from O(n) to O(logn).
Do you know anything about fail-fast? Fail-fast means to Fail quickly.
More content see fail – fast mechanism: blog.csdn.net/chenssy/art…
Iterator’s fail-fast property works with the current collection, so it is not affected by any changes in the collection. All the collection classes in the java.util package are designed to be fail->fast, while the collection classes in java.util. Concurrent are fail-safe. When detected are traverse a collection of structure is changed, the Fail – fast iterator throw ConcurrentModificationException, and Fail – safe never throw ConcurrentModificationException iterator.
About dates Is SimpleDateFormat thread-safe? Unfortunately, all DateFormat implementations, including SimpleDateFormat, are not thread-safe, so you should not use them in multithreaded sequences unless they are used in an external thread-safe environment. For example, restrict SimpleDateFormat to ThreadLocal. If you don’t, you may get incorrect results when parsing or formatting dates. Therefore, I highly recommend the Joda-time library for all practices in date and time handling.
How do I format dates? In Java, you can use the SimpleDateFormat class or the Joda-time library to format dates. The DateFormat class allows you to format dates in a variety of popular formats. See the sample code in the answer that demonstrates formatting dates into different formats, such as DD-MM-YYYY or ddMMyyyy.
No one is unfamiliar with exception architecture in Java, and more information about exception architecture can be found in this section
Vernacular exception mechanism: blog.csdn.net/dd864140130…
What is the exception chain details directly refer to the above vernacular exception mechanism, not to explain.
Throw is used to actively throw an instantiated object of the java.lang.Throwable class. This means that you can throw an Error or an Exception using the keyword throw, as in: Throw new IllegalArgumentException(” size must be multiple of 2 “). As part of the method declaration and signature, throws an exception so that the caller can handle it. In Java, any unchecked checked exception is forced to be declared in the THROWS clause.
The Serializable interface is an interface that serializes Java classes so that they can be transferred over the network or their state can be stored on disk. Is the default serialization method built into the JVM, which is expensive, fragile, and insecure. Externalizable allows you to control the entire serialization process, specify specific binary formats, and add security mechanisms.
The JVM features are platform independent. A very important feature of the Java language is its platform-independence. The use of Java virtual machine is the key to achieve this feature. Normal high-level languages need to be compiled into at least different object code if they are to run on different platforms. With the introduction of the Java language VIRTUAL machine, the Java language does not need to be recompiled when running on different platforms. The Java Language Usage Pattern The Java Virtual machine shields platform-specific information, allowing Java language compilers to run on multiple platforms without modification, simply by generating object code (bytecode) that runs on the Java Virtual machine. When the Java virtual machine executes bytecodes, it interprets the bytecodes as machine instructions on a specific platform.
A quick explanation of class loaders and class loaders will ask you about the four types of loaders and the parental delegation model,
For more information, see Understanding JVM loaders in Depth:
Blog.csdn.net/dd864140130…
In a VM, the heap and the stack belong to different memory areas and are used for different purposes. Stacks are often used to hold method frames and local variables, while objects are always allocated on the heap. Stacks are typically smaller than the heap and are not shared between multiple threads, whereas the heap is shared by all threads across the entire JVM.
Basic data types are allocated on the stack rather than references to variables and objects.
Heap memory is used to hold objects and arrays created by new.
Class variables (static modified variables). The program allocates memory for class variables in the heap as soon as they are loaded. Memory addresses in the heap are stored on the stack.
Instance variables: When you use the keyword new Java system in the heap is not necessarily a continuous space is assigned to the variable, is based on scattered heap memory address, through the hash algorithm conversion as a long string of Numbers to represent the variable “physical location in the heap,” instance variable life cycle – after the instance variable reference lost, Puts the garbage collector on the recyclable “list”, but does not immediately free up memory in the heap.
Local variable: declared in a method or section of code (such as a for loop), which opens up memory on the stack when executed, and is freed as soon as the local variable is out of scope.
Are other Java applications big-endian or small-endian? XML parsing: DOM, SAX, PULL
DOM: Memory consumption: Read all the XML documents into memory, then use the DOM API to access the tree structure and retrieve the data. This is easy to write, but it consumes memory. If the data is too large, the phone is not cool enough, the phone may directly crash
SAX: High parsing efficiency, occupies less memory, based on event-driven: To put it more simply, the document is scanned sequentially. When the document begins and ends, the element begins and ends, and the document ends, the event handler is notified, and the event handler does the corresponding actions, and then the same scan continues until the document ends.
PULL: Similar to SAX, it is event-driven, and we can call its next () method to get the next parsing event (that is, start document, end document, start tag, end tag), You can call XmlPullParser’s getAttributte() method to get the value of the attribute when you are on an element, or you can call its nextText() to get the value of the node.
While JDK 1.7 is not as big as JDK 5 and 8, there are a number of new features, such as try-with-resource statements, that allow you to use streams or resources without having to manually close them. Java does this automatically. Fork-join pooling implements the Java version of Map-Reduce to some extent. Allow String variables and text in Switch. The diamond operator (<>) is used for type inference and eliminates the need to declare generics on the right side of variable declarations, resulting in stronger, cleaner code that can be read and written.
Java 8 is a groundbreaking release in Java history. Here are five key features in JDK 8: Lambda expressions, which allow anonymous functions to be passed like objects through the Stream API, take full advantage of modern multicore cpus to write very concise code in the Date and Time API. Finally, there is a stable, simple Date and Time library that you can use to extend methods. Now, Interfaces can have static, default methods. Repeat annotations. Now you can use the same annotation multiple times on the same type.
What’s the difference between Maven and ANT? While both are build tools for creating Java applications, Maven does more, providing a standard Java project structure based on the concept of convention over configuration, while automatically managing dependencies (JAR files that the application depends on).
JDBC best practices preferentially use batch operations to insert and update data
Use preparedStatements to avoid SQL vulnerabilities
Use data connection pooling
Get the result set by column name
Best practices for IO operations use buffered IO classes and do not read bytes or characters individually
Use NIO and NIO 2 or AIO instead of BIO
Close the flow in finally
Use memory-mapped files for faster IO