Whether you are a new programmer or a veteran, you must have encountered a thread-related problem in your interview. An important feature of the Java language is the built-in support for concurrency, which makes Java popular with businesses and programmers. Most well-paid Java development positions require developers to be proficient in multithreaded technology and have extensive experience in Java program development, debugging, and optimization, so thread-related issues are often mentioned in interviews.
In a typical Java interview, the interviewer asks the basic concepts of the thread, such as: why you need to use threads, how to create threads, and how to create threads better (for example, inheriting the thread class or calling the Runnable interface), And then gradually asked what concurrency problems were like in Java concurrency programming, Java memory model, JDK1.5 introduced higher-order concurrency tools, concurrent programming common design patterns, classic multithreading problems such as producer consumers, philosophers dining, A reader or a simple bounded buffer problem. Just knowing the basic concept of threading is far from enough, you must know how to deal with the concurrency problems such as deadlock, race condition, memory conflict and line Cheng. With these tips, you can easily handle multithreading and concurrent interviews.
It's normal for many Java programmers to go to the interview before the interview. Because collecting face questions and exercises took time, I collected 50 hot questions from many interviewers about Java multithreading and concurrency. I only collected more new face questions and did not provide all the answers. Presumably smart you are aware of these issues, and if you do not understand the problem, you can use Google to find the answer. If you can't find the answer, you can ask me for help in the comments of the article. You can also find some answers here. Java thread question top 12.
50 Java Thread Surface questions
Here are some popular interview questions about Java threading, which you can use to prepare for the interview.
1) What is a thread?
A thread is the smallest unit that the operating system can perform operations on, which is included in the process and is the actual operating unit of the process. Programmers can use it for multiprocessor programming, and you can speed up operations-intensive tasks using multithreading. For example, if a thread takes 100 milliseconds to complete a task, it takes 10 milliseconds to complete the task with 10 threads. Java provides excellent support for multithreading at the language level, and it is also a good selling point. For more details, please click here.
2) What is the difference between threads and processes?
A thread is a subset of processes, a process can have many threads, and each thread performs different tasks in parallel. Different processes use different memory spaces, and all threads share the same amount of memory space. Don't confuse it with stack memory, each thread has a separate stack of memory to store local data. For more details, please click here.
3) How do I implement threads in Java?
There are two ways to speak at the language level. An instance of the Java.lang.Thread class is a thread but it needs to invoke the Java.lang.Runnable interface to execute, since the thread class itself is the runnable interface of the call so you can inherit Java.lang.Thread Class or call the Runnable interface directly to override the run () method to implement the thread. For more details, please click here.
4) using runnable or thread?
The question is the follow-up, and we all know that we can implement threads by inheriting the thread class or calling the Runnable interface, and the question is, what better way? Under what circumstances should it be used? This question is easy to answer if you know that Java does not support multiple inheritance of classes, but allows you to invoke multiple interfaces. So if you're going to inherit other classes, of course it's OK to call the Runnable interface. For more details, please click here.
6) What is the difference between the start () and run () methods in the Thread class?
This question is often asked, but it is still possible to differentiate from the way in which the participants understand the Java threading model. The start () method is used to start the newly created thread, and start () calls the run () method internally, which is not the same as calling the run () method directly. When you call the run () method, only the original thread is called, no new thread is started, and the start () method starts the new thread. For more discussion please click here
7) What is the difference between runnable and callable in Java?
Both runnable and callable represent tasks that you want to perform in different threads. Runnable from the JDK1.0 began, callable is in the JDK1.5 increase. The main difference is that the callable call () method can return a value and throw an exception, while the runnable run () method does not have these features. The callable can return a future object loaded with calculated results. My blog is described in more detail.
8) What is the difference between Cyclicbarrier and Countdownlatch in Java?
Both Cyclicbarrier and Countdownlatch can be used to allow a group of threads to wait for other threads. Unlike Cyclicbarrier, Countdownlatch cannot be reused. Click here for more information and sample code.
9) What is the Java memory model?
The Java memory model prescribes and directs Java programs to behave in a deterministic manner between different memory architectures, CPUs, and operating systems. It is especially important in the case of multithreading. The Java memory model guarantees that changes made by one thread can be visible to other threads, and that they are first-rate. This relationship defines rules that allow programmers to have a clearer idea of concurrent programming. For example, prior sex ensures that:
- The code within the thread can be executed in a sequential order, which is called the program order rule.
- For the same lock, an unlock operation must occur after another lock operation that occurs after the time, also known as a pipe lock rule.
- The previous pair
volatile
's write operation is volatile
also called a variable rule before the next read Operation volatile
.
- Any operation within a thread must be called after the start () Call of this thread, also known as the thread initiation rule.
- A thread terminates the rule before all operations on a thread are terminated.
- The end operation of an object must also be called an object finalization rule after the object is constructed.
- Transitivity
I strongly recommend that you read the 16th chapter of Java Concurrency Programming practice to deepen your understanding of the Java memory model.
What are the volatile variables in Java?
Volatile is a special modifier that can only be used by member variables. Multithreaded operations on member variables are transparent to other threads in the absence of a synchronization class for Java concurrency programs. The volatile variable guarantees that the next read will occur after the previous write operation, which is the volatile variable rule for the previous question. Click here to see more about volatile content.
11) What is thread safety? is vector a thread-safe class? (See here)
If your code is in a process where multiple threads are running at the same time, these threads may run the code at the same time. If the result of each run is the same as the single-threaded run, and the value of the other variable is the same as expected, it is thread-safe. The same instance object of a thread-safe counter class will not have a computational error if it is used by multiple threads. Obviously you can divide the collection classes into two groups, thread-safe and non-thread-safe. Vectors are thread-safe with synchronous methods, and ArrayList similar to it are not thread-safe.
What are race conditions in Java? Give an example.
A race condition causes the program to have some bugs in the concurrency situation. Multi-threaded to some of the resources of the competition when the situation will produce a race condition, if the first to execute the program competition failure platoon to execute, then the entire program will appear some uncertain bugs. This bugs is difficult to find and will recur because of random competition between threads. An example is a disorderly process, see the answer.
How do I stop a thread in Java?
Java provides a rich API but does not provide an API for stopping threads. JDK 1.0 originally had some control methods like Stop (), suspend (), and resume () but because of the potential deadlock threat they were deprecated in subsequent JDK versions, the Java API designers did not provide a compatible and thread-safe way to stop a thread. When the run () or call () method finishes executing, the thread ends automatically, and if you want to end a thread manually, you can use the volatile Boolean variable to exit the run () method's loop or cancel the task to break thread. Click here to view the sample code.
14) What happens when a thread runs out of an exception?
This is a very tricky Java interview that I met in an interview, which simply says that the thread will stop executing if the exception is not captured. Thread.uncaughtexceptionhandler is an inline interface for dealing with abrupt interruptions of threads caused by uncaught exceptions. When an uncaught exception causes the thread to break, the JVM uses Thread.getuncaughtexceptionhandler () To query the thread's Uncaughtexceptionhandler and pass the thread and exception as arguments to the handler's Uncaughtexception () method for processing.
15) How do I share data between two threads?
You can do this by sharing objects, or by using a data structure that is concurrent like a blocking queue. This tutorial, "Java Inter-thread communication," which involves sharing objects between two threads, implements the producer consumer model with the wait and notify methods.
What is the difference between notify and Notifyall in Java?
This is another tricky question, because multithreading can wait for single-monitor locks, and Java API designers provide methods to notify them when they wait for conditions to change, but these methods are not fully implemented. The Notify () method does not wake up a specific thread, so only one thread waits for it to be useful. Notifyall () Wakes all threads and allows them to scramble for locks to ensure that at least one thread can continue to run. My blog has more detailed information and sample code.
17) Why wait, notify and notifyall These methods are not inside the thread class?
This is a design-related issue that examines the interviewer's view of the existing system and some common but seemingly irrational things. To answer these questions, you need to explain why it makes sense to put these methods in the object class, and why not put them in the thread class. One obvious reason is that the locks provided by Java are object-level rather than thread-level, and each object has a lock, which is obtained through the thread. The wait () method in the calling object is meaningful if the thread waits for some locks. If the wait () method is defined in the thread class, it is not obvious which lock the thread is waiting for. Simply put, because Wait,notify and Notifyall are both lock-level operations, they are defined in the object class because the locks belong to the objects. You can also check this article to learn more.
18) What is a threadlocal variable?
Threadlocal is a special variable in Java. Each thread has a threadlocal that each thread has its own independent variable, and the race condition is completely eliminated. It is a good way to get thread-safe for creating expensive objects, such as you can use threadlocal to make SimpleDateFormat thread-safe, because that class is expensive to create and each call needs to create a different instance, so it's not worth using it in a local scope. If you provide a copy of your own unique variables for each thread, you will be much more efficient. First, it reduces the number of expensive objects created by multiplexing. Second, you get thread safety without using high-cost synchronization or immutability. Another good example of thread-local variables is the Threadlocalrandom class, which reduces the number of expensive random objects created in a multithreaded environment. See answers to learn more.
19) What is Futuretask?
In a Java concurrency program, Futuretask represents an asynchronous operation that can be canceled. It has the methods of starting and canceling operation, whether the query operation is complete and retrieving the result of operation. The result can be retrieved only when the operation is complete, and the Get method will block if the operation has not been completed. A Futuretask object can be wrapped on an object that calls callable and runnable, because Futuretask also calls the Runnable interface so it can be submitted to executor for execution.
What is the difference between interrupted and Isinterruptedd methods in Java?
The main difference between interrupted () and isinterrupted () is that the former clears the interrupt state and the latter does not. The Java Multi-threading interrupt mechanism is implemented with an internal identity, and calling Thread.Interrupt () to break a thread sets the interrupt ID to true. The interrupt state is zeroed when the interrupt thread calls the static method thread.interrupted () to check the break state. The non-static method, isinterrupted (), is used to query the interrupt state of other threads without changing the interrupt status identifier. Simply put, any method that throws a Interruptedexception exception will clear the interrupt state. In any case, the interrupt state of a thread can be changed by other threads calling interrupts.
21) Why are the wait and notify methods called in the synchronization block?
The main reason is that the Java API enforces this, and if you don't, your code throws a Illegalmonitorstateexception exception. Another reason is to avoid a race condition between wait and notify.
22) Why should you check the waiting conditions in the loop?
A thread that is in a wait state may receive an error alert and a pseudo-wake, and if the wait condition is not checked in the loop, the program exits without satisfying the end condition. Therefore, when a waiting thread wakes up, it cannot assume that its original wait state is still valid, and it may change after the Notify () method call and before the waiting thread wakes up. That's why using the Wait () method in a loop works better, so you can create a template in Eclipse and call wait and notify. If you want to learn more about this issue, I recommend that you read thethreads and synchronization chapters in effective Java.
) What is the difference between a synchronous collection in Java and a concurrent collection?
Both synchronous and concurrent collections provide the appropriate thread-safe collection for multithreading and concurrency, although the concurrency collection is more extensible. Before Java1.5, programmers had only synchronized sets to use and in the multi-threaded concurrency will lead to contention, hindering the system's extensibility. JAVA5 introduces concurrent collections like Concurrenthashmap, which not only provides thread safety but also improves scalability with modern technologies such as lock separation and internal partitioning. For more details, see the answer.
What is the difference between heap and stack in Java?
Why is this problem categorized in multi-threaded and concurrent-facing questions? Because the stack is an area of memory that is closely related to threads. Each thread has its own stack memory, which is used to store local variables, method parameters, and stack calls, and variables stored in one thread are not visible to other threads. The heap is a common area of memory shared by all threads. Objects are created in the heap, in order to increase the efficiency of the thread will get a cache from the heap to its own stack, if multiple threads use the variable can cause problems, then the volatile variable can play a role, it requires the thread to read the value of the variable from main memory.
For more details, see the answer.
25) What is a thread pool? Why use it?
Creating threads takes expensive resources and time, and if the task is to create a thread, the response time is longer and the number of threads a process can create is limited. To avoid these problems, when the program starts, it creates several threads that respond to processing, called the thread pool, which is called a worker thread. Starting with JDK1.5, the Java API provides a executor framework that allows you to create different thread pools. For example, a single thread pool, one task at a time, a fixed number of thread pools or a pool of cache threads (an extensible thread pool for programs that are suitable for many short-lived tasks). See this article for more details.
26) How to write code to solve the problem of producer consumers?
In reality, many of the threading problems you solve belong to the producer consumer model, which is a thread production task for other threads to consume, and you must know how to communicate between threads to solve this problem. The lower-level approach is to use wait and notify to solve the problem, the more praise is to use semaphore or Blockingqueue to implement the producer consumer model, this tutorial has to implement it.
27) How to avoid deadlocks?
Deadlock in Java Multi-threading
Deadlock refers to two or more processes in the process of execution, because of the competition for resources caused by a mutual waiting phenomenon, if there is no external force, they will not go forward. This is a serious problem because a deadlock will cause your program to hang and cannot complete the task, the following four conditions must be met for a deadlock to occur:
- Mutex condition: A resource can only be used by one process at a time.
- Request and hold condition: When a process is blocked by a request for resources, it remains in place for the resources that have been obtained.
- Non-deprivation: the resources that the process has acquired cannot be forcibly stripped until the end of use.
- Cyclic wait condition: a cyclic waiting resource relationship is formed between several processes.
The simplest way to avoid deadlocks is to stop the loop waiting condition, set the flags, sort all the resources in the system, and stipulate that all process request resources must operate in a certain order (ascending or descending) to avoid deadlocks. This tutorial has code examples and discussion details to avoid deadlocks.
What is the difference between a live lock and a deadlock in Java?
This is an extension of the above topic, and the difference between a live lock and a deadlock is that the state of a thread or process in a live lock is constantly changing, and a live lock can be considered a special kind of starvation. A realistic example of a live lock is two people in a narrow corridor, two people are trying to avoid each other to allow each other to pass, but because the direction of avoidance is the same result in the end no one can pass the corridor. Simply put, the main difference between a live lock and a deadlock is that the state of the former process can be changed but cannot continue to execute.
29) How do I detect if a thread has a lock?
I never knew we could detect if a thread had a lock until I took a phone interview. In Java.lang.Thread there is a method called Holdslock (), which returns true if and only if the thread has a lock on a specific object. You can view this article to learn more.
30) How do you get the thread stack in Java?
There are several ways to get the thread stack for a Java process for different operating systems. When you get the thread stack, the JVM either saves the state of all the threads to the log file or outputs it to the console. In Windows you can use the CTRL + BREAK key combination to get the thread stack, Linux under the kill-3 command. You can also use the Jstack tool to get it, which operates on the thread ID and you can find the ID using the JPS tool.
) which parameter in the JVM is the small stack stack used to control the thread
The problem is simple, and the-XSS parameter is used to control the stack size of the thread. You can view a list of JVM configurations to learn more about this parameter.
What is the difference between synchronized and Reentrantlock in Java?
Java has had some drawbacks in the past for a long time only through the Synchronized keyword to achieve mutual exclusion. For example, you cannot extend a method or block boundary outside of a lock, and you cannot cancel it while trying to acquire a lock. Java 5 provides more complex control through the lock interface to address these issues. The Reentrantlock class implements Lock, which has the same concurrency and memory semantics as synchronized, and it also has extensibility. You can view this article to learn more
33) There are three threads t1,t2,t3, how to ensure that they are executed sequentially?
There are several ways to get threads to execute in a particular order in multiple threads, and you can use the join () method of the thread class to start another thread in one thread, and another thread to finish the thread. In order to ensure the order of three threads you should start the last one (T3 call t2,t2 call T1) so T1 will be completed first and T3 finalized. You can view this article to learn more.
How does the yield method in the thread class work?
The yield method can pause the currently executing thread object, allowing other threads with the same priority to execute. It is a static method and only guarantees that the current thread abandons the CPU and does not guarantee that other threads will be able to occupy the CPU, and that the thread executing yield () is likely to be executed immediately after entering the paused state. Click here to find out more about the yield method.
What is the concurrency level of concurrenthashmap in Java?
Concurrenthashmap the actual map into several parts to achieve its extensibility and thread safety. This partitioning is obtained using concurrency, which is an optional parameter to the Concurrenthashmap class constructor, with a default value of 16, which avoids contention in multithreaded situations. For more concurrency and internal resizing please read my article how Concurrenthashmap works in Java.
What is semaphore in Java?
Semaphore in Java is a new synchronization class, which is a counting signal. Conceptually, the semaphore maintains a set of permissions in a conceptual sense. If necessary, block each acquire () before the license is available, and then obtain the license. Each release () adds a license that may release a blocked fetch. However, instead of using the actual license object, semaphore only counts the number of available licenses and takes action accordingly. Semaphores are often used in multithreaded code, such as database connection pooling. For more details, please click here.
37) If you submit a task, the thread pool queue is full. What will happen when the meeting is made?
This question is tricky to ask, and many programmers think the task will block until the thread pool queue is empty. In fact, if a task cannot be scheduled to execute, then the Threadpoolexecutor's submit () method throws a Rejectedexecutionexception exception.
) What is the difference between the submit () and execute () methods in the Java thread pool?
Two methods can submit a task to the thread pool, the return type of the Execute () method is void, it is defined in the executor interface, and the Submit () method can return a future object holding the result of the calculation, which is defined in the Executorservice interface. It extends the executor interface, and other thread pool classes like Threadpoolexecutor and Scheduledthreadpoolexecutor have these methods. For more details, please click here.
39) What is a blocking method?
The blocking method means that the program waits for the method to complete without doing anything else, and the ServerSocket accept () method is to wait for the client to connect. The blocking here means that the current thread is suspended until the result of the call returns, until the results are returned. In addition, there are asynchronous and non-blocking methods that are returned before the task is completed. For more details, please click here.
) is swing thread-safe? Why?
You can be sure to answer that swing is not thread-safe, but you should explain the reason for the answer even if the interviewer doesn't ask you why. When we say that swing is not thread-safe and often mentions its components, which cannot be modified in multiple threads, all updates to GUI components are done in the AWT thread, and swing provides both synchronous and asynchronous callback methods to update. Click here to see more about swing and thread safety.
What is the difference between invokeandwait and Invokelater in Java?
These two methods are provided by the swing API to Java developers to update GUI components from the current thread instead of the event dispatch thread. Invokeandwait () updates the GUI component synchronously, such as a progress bar, and once the progress is updated, the progress bar is changed accordingly. If the progress is tracked by multiple threads, call the Invokeandwait () method to request the event dispatch thread to update the component accordingly. The Invokelater () method is called to update the component asynchronously. For more details, please click here.
How are those methods in the Swing API thread-safe?
This issue also mentions swing and thread safety, although the components are not thread-safe but there are methods that can be safely called by multithreading, such as repaint (), revalidate (). JTextComponent's SetText () method and JTextArea's insert () and append () methods are also thread-safe.
43) How do I create a immutable object in Java?
This problem does not seem to have anything to do with multithreading, but immutability helps to simplify already complex concurrent programs. The immutable object can be shared without synchronization, reducing the synchronization overhead when concurrent access is made to the object. However, Java does not @immutable this annotation, to create an immutable class, to implement the following steps: By constructing a method to initialize all members, do not provide setter methods to variables, declare all members as private, so that directly access to these members, in the Getter method , do not directly return the object itself, but instead clone the object and return a copy of the object. My article how to makes an object immutable in Java has a detailed tutorial that you can confidently read through.
What is Readwritelock in Java?
Generally speaking, read-write locks are the result of lock separation techniques used to improve concurrent program performance. Readwritelock in Java is a new interface in Java 5, a readwritelock maintains a pair of associated locks, one for read-only operations and one for writing. In the absence of a write thread, a read lock may be held by multiple read threads at the same time. Write locks are exclusive, and you can use the Reentrantreadwritelock in the JDK to implement this rule, which supports up to 65,535 write locks and 65,535 read locks.
45) What is a busy loop in multi-threading?
A busy loop is when a programmer uses a loop to wait for a thread, unlike the traditional method wait (), sleep () or yield (), which discards CPU control, and the busy loop does not abandon the CPU, it is running an empty loop. The purpose of this is to preserve the CPU cache, in which a waiting thread wakes up in a multi-core system and may run in another kernel, which rebuilds the cache. It can be used to avoid rebuilding the cache and reducing the time it takes to wait for a rebuild. You can check this article for more information.
What is the difference between a volatile variable and a atomic variable?
This is an interesting question. First, the volatile variable and the atomic variable look alike, but the function is different. Volatile variables ensure that the antecedent relationship, that is, the write operation occurs before subsequent reads, but it does not guarantee atomicity. For example, if you modify the count variable with volatile, then the count++ operation is not atomic. The atomic method provided by the Atomicinteger class allows this operation to be atomic, such as the Getandincrement () method, which atomically increments the current value by one, and other data types and reference variables can be similarly manipulated.
47) What happens if a thread inside a synchronization block throws an exception?
This problem is a lot of Java programmers, if you can think of whether the lock release this clue to answer still a little hope to correct. Regardless of whether your synchronization block is normal or abnormal exit, the thread inside will release the lock, so the contrast lock interface I prefer the synchronization block, because it does not need me to expend the effort to release the lock, this function can release the lock implementation in the finally block.
48) What is the double check lock of the single case mode?
This question is often asked in a Java interview, but the interviewer's satisfaction with answering the question is only 50%. Half of the people can't write double check lock and half of the people can't tell the hidden trouble and how the Java1.5 fix it. It's actually an old way to create a thread-safe singleton, and when the singleton instance is first created it tries to optimize performance with a single lock, but because it's too complicated in JDK1.4 it's a failure, and I don't like it personally. Anyway, even if you don't like it, you need to know it, because it's often asked. You can see how double checked locking on Singleton works this article for more information.
49) How do I create a thread-safe singleton in Java?
This is the follow-up to the question above, and if you don't like double lock and the interviewer asks for an alternative to creating the Singleton class, you can use the JVM's class-Loading and static-variable initialization features to create singleton instances, or use enumeration types to create Singleton, I like to use this method very much. You can check this article for more information.
50) write out 3 multithreading best practices that you follow
I like the problem best, and I'm sure you'll follow some best practices when writing concurrency code to improve performance. The following three best practices I think most Java programmers should follow:
- Give your thread a meaningful name.
This makes it easy to find bugs or tracks. Orderprocessor, quoteprocessor or tradeprocessor this name than Thread-1. Thread-2 and Thread-3 are much better, give the thread a name related to the task it is going to accomplish, and all the main frameworks and even the JDK follow this best practice.
- Avoid locking and narrowing the range of synchronizations
Lock costs are expensive and context switches are more time-consuming, try to minimize the use of synchronization and locks, and narrow the critical section. So I prefer the sync block to the synchronization method, which gives me absolute control over the lock.
- Multi-use sync class less wait and notify
First, Countdownlatch, Semaphore, Cyclicbarrier, and Exchanger, these synchronization classes simplify coding operations, and it is difficult to control complex control flows with wait and notify. Second, these classes are written and maintained by the best companies in the subsequent JDK and they will continue to be optimized and perfected, using these higher-level synchronization tools your program can effortlessly get optimized.
- Multiple concurrent collections with less synchronous collections
This is another best practice that is easy to follow and benefit enormously, and concurrent collections are more extensible than synchronous collections, so it is better to use concurrent collections in concurrent programming. If you need to use map next time, you should first think of using Concurrenthashmap. My article Java Concurrency collection is described in more detail.
51) How do I force a thread to start?
This problem is like how to enforce Java garbage collection, and there is no way to think about it, although you can use System.GC () to do garbage collection, but it is not guaranteed to succeed. There is no way to force a thread to start in Java, which is controlled by the thread scheduler and Java does not advertise the associated API.
What is the fork join framework in Java?
The fork join framework is an efficient tool in JDK7 that allows Java developers to take full advantage of multiprocessor on modern servers. It is designed specifically for those that can be recursively partitioned into many sub-modules, with the aim of using all available processing power to enhance the performance of the program. A huge advantage of the fork join framework is that it uses a work-stealing algorithm that can be executed by a worker thread that is able to perform more tasks from other threads. You can check this article for more information.
What is the difference between calling the wait () and sleep () methods in Java Multi-threading?
Wait and sleep in Java programs cause some form of pause, which can meet different needs. The wait () method is used for inter-thread communication, and if the wait condition is true and other threads are awakened, it releases the lock, and the sleep () method simply frees the CPU resources or causes the current thread to stop executing for a period of time, but does not release the lock. You can check this article for more information.
These are the 50 popular Java multithreading and concurrency test questions. I did not share the answers to all the questions but provided enough hints and clues for future readers to find the answers. If you really can't find the answer to a question, contact me and I'll add it. This article can be used not only to prepare an interview, but also to check your understanding of threading issues such as multithreading, concurrency, design patterns and race conditions, deadlocks, and thread Cheng. I'm going to turn this article into a collection of all the Java multithreading problems, but without your help the horror can't be done, and you can share with me any other questions, including those you've been asked but haven't found. This article is useful for beginners or experienced Java developers, and you'll benefit from reading it in two or three or five or six years. It can be extended to beginners especially useful because this can expand their knowledge, I will constantly update these questions, you can ask questions in the comments later in the article, share and answer questions together to complete this piece of questions.
Java thread surface question Top 50