This article helps you master the basic knowledge of Java multithreading to correspond to problems you encounter in the future. The specific content is as follows
1. Java multi-threaded interview questions
1. What is the difference between a process and a thread?
A process is a self contained running environment, which can be regarded as a program or an application. A thread is a task that is executed in a process. The Java runtime environment is a single process that contains different classes and programs. Threads can be called lightweight processes. Threads require fewer resources to create and reside in the process and can share resources in the process.
2. What are the benefits of multi-threaded programming?
In a multi-threaded program, multiple threads are executed concurrently to improve the efficiency of the program, and the CPU will not enter an idle state because a certain thread needs to wait for resources. Multiple threads share heap memory, so creating multiple threads to perform some tasks is better than creating multiple processes. For example, Servlets are better than CGI because Servlets support multithreading while CGI does not.
3. What is the difference between user threads and daemon threads?
When we create a thread in a Java program, it is called a user thread. A daemon thread is a thread that executes in the background and does not block the JVM terminated. When no user thread is running, the JVM closes the program and exits. The child thread created by a daemon thread is still a daemon thread.
4. How do we create a thread?
There are two ways to create threads: one is to implement the Runnable interface, then pass it to the Thread constructor, and create a Thread object; the other is to directly inherit the Thread class. For more information, you can read this article on how to create threads in Java.
5. What are the different thread life cycles?
When we create a new thread in a Java program, its status is New. When we call the start() method of the thread, the state is changed to Runnable. The thread scheduler allocates CPU time to threads in the Runnable thread pool and changes their state to Running. Other thread states include Waiting, Blocked and Dead. Read this article to learn more about thread lifecycles.
6. Can I directly call the run() method of the Thread class?
Of course, but if we call Thread's run() method, it will behave the same as the normal method. In order to execute our code in a new thread, the Thread.start() method must be used.
7. How to pause a running thread for a period of time?
We can use the Sleep() method of the Thread class to pause the thread for a period of time. It should be noted that this does not cause the thread to terminate. Once the thread is awakened from hibernation, the thread's state will be changed to Runnable, and according to the thread scheduling, it will be executed.
8. What is your understanding of thread priority?
Each thread has priority. Generally speaking, high-priority threads will have priority when running, but this depends on the implementation of thread scheduling, which is related to the operating system (OS dependent). We can define the priority of threads, but this does not guarantee that high-priority threads will execute in front of low-priority threads. Thread priority is an int variable (from 1-10), 1 represents the lowest priority and 10 represents the highest priority.
9. What are thread schedulers and time slicing?
A thread scheduler is an operating system service that is responsible for allocating CPU time to threads in Runnable state. Once we create a thread and start it, its execution depends on the implementation of the thread scheduler. Time sharding refers to the process of allocating available CPU time to available Runnable threads. The allocated CPU time can be based on thread priority or thread waiting time. Thread scheduling is not controlled by Java virtual machines, so it is better to control it by the application (that is, don't let your program depend on thread priorities).
10. In multithreading, what is context-switching?
Context switching is a process of storing and restoring CPU state, which enables thread execution to resume execution from interrupt points. Context switching is a basic feature of multi-task operating systems and multi-threaded environments.
11. How do you make sure that the thread where the main() method is located is the last thread that ends in the Java program?
We can use the joint() method of the Thread class to ensure that all threads created by the program end before the main() method exits. Here is an article about the joint() method of the Thread class.
12. How do threads communicate?
When inter-thread resources can be shared, inter-thread communication is an important means to coordinate them. The wait()/notify()/notifyAll() method in the Object class can be used to communicate between threads about the state of locks about resources. Click here for more about thread wait, notify and notifyAll.
13. Why are the thread communication methods wait(), notify() and notifyAll() defined in the Object class?
Each object in Java has a lock (monitor, which can also be a monitor) and wait(), notify() and other methods are used to wait for the object's lock or notify other thread objects to be available. There are no locks and synchronizers available for any object to use in Java threads. This is why these methods are part of the Object class, so that every class in Java has basic methods for inter-thread communication
14. Why must wait(), notify() and notifyAll() be called in a synchronization method or a synchronization block?
When a thread needs to call the wait() method of the object, the thread must have the lock of the object. Then it releases the lock of the object and enters the waiting state until other threads call the notify() method on the object. Similarly, when a thread needs to call the object's notify() method, it will release the object's lock so that other threads waiting to get the object's lock. Since all these methods require threads to hold the object's lock, they can only be implemented through synchronization, so they can only be called in the synchronization method or the synchronization block.
15. Why are the sleep() and yield() methods of the Thread class static?
The sleep() and yield() methods of the Thread class will run on the currently executing thread. So it doesn't make sense to call these methods on other threads that are in a waiting state. That's why these methods are static. They can work in the currently executing thread and avoid the programmer's mistaken belief that these methods can be called in other non-running threads.
16. How to ensure thread safety?
There are many ways to ensure thread safety in Java - synchronization, use atomic concurrent classes, implement concurrent locks, use volatile keywords, use invariant classes and thread-safe classes. You can learn more in the thread safety tutorial.
17. What is the role of volatile keyword in Java?
When we use the volatile keyword to modify a variable, the thread will directly read the variable and do not cache it. This ensures that the variables read by the thread are consistent in memory.
18. Which is the better choice, the synchronization method or the synchronization block?
Synchronous blocks are a better choice because it won't lock the entire object (and of course you can also let it lock the entire object). The synchronization method locks the entire object, even if there are multiple unrelated synchronization blocks in the class, which usually causes them to stop executing and need to wait to obtain the lock on the object.
19. How to create a daemon thread?
Use the setDaemon(true) method of the Thread class to setDaemon(true) method to set the thread as a daemon thread. It should be noted that this method needs to be called before calling the start() method, otherwise an IllegalThreadStateException will be thrown.
20. What is ThreadLocal?
ThreadLocal is used to create local variables for threads. We know that all threads of an object will share its global variables, so these variables are not thread-safe and we can use synchronization techniques. But when we don't want to use synchronization, we can choose the ThreadLocal variable.
Each thread will have their own Thread variables, which can use the get()/set() method to get their default values or change their values internally. ThreadLocal instances usually want them to be associated with thread state as private static attributes. In this article, you can see a small program about ThreadLocal.
21. What is Thread Group? Why is it not recommended?
ThreadGroup is a class whose purpose is to provide information about thread groups.
The ThreadGroup API is relatively weak, and it doesn't offer more features than Thread. It has two main functions: one is to obtain a list of active threads in the thread group; the other is to set an uncaught exception handler for threads. However, in Java 1.5, the Thread class also added the setUncaughtExceptionHandler(UncaughtExceptionHandler eh) method, so the ThreadGroup is outdated and it is not recommended to continue using it.
t1.setUncaughtExceptionHandler(new UncaughtExceptionHandler(){ @Override public void uncaughtException(Thread t, Throwable e) { System.out.println("exception occurred:"+e.getMessage()); }}); 22. What is a Java thread dump and how to get it?
Thread dump is a list of JVM active threads that are very useful for analyzing system bottlenecks and deadlocks. There are many ways to get thread dumps - using Profiler, Kill -3 command, jstack tool, etc. I prefer jstack tool because it is easy to use and comes with JDK. Since it is a terminal-based tool, we can write some scripts to timely generate thread dumps for analysis. Read this document to learn more about generating thread dumps.
23. What is a deadlock? How to analyze and avoid deadlocks?
Deadlock refers to the situation where more than two threads are blocked forever. This situation requires at least two threads and more than two resources.
To analyze deadlocks, we need to view the thread dump of the Java application. We need to find out those threads with state BLOCKED and the resources they are waiting for. Each resource has a unique id. Using this id we can find out which threads already have its object lock.
Avoiding nested locks, using only locks where they are needed and avoiding indefinite waiting are the usual ways to avoid deadlocks, read this article to learn how to analyze deadlocks.
24. What is the Java Timer class? How to create a task with a specific time interval?
java.util.Timer is a tool class that can be used to schedule a thread to execute at a certain time in the future. The Timer class can be arranged by scheduling one-time tasks or periodic tasks.
java.util.TimerTask is an abstract class that implements the Runnable interface. We need to inherit this class to create our own timed tasks and use Timer to arrange its execution.
25. What is a thread pool? How to create a Java thread pool?
A thread pool manages a set of worker threads, and it also includes a queue for placing tasks waiting to be executed.
java.util.concurrent.Executors provides an implementation of the java.util.concurrent.Executor interface for creating thread pools. The thread pool example shows how to create and use a thread pool, or read the ScheduledThreadPoolExecutor example to learn how to create a periodic task.
2. Java concurrent interview questions
1. What is atomic operation? What atomic classes are there in the Java Concurrency API?
Atomic operation refers to an operation task unit that is not affected by other operations. Atomic operations are necessary means to avoid data inconsistency in a multi-threaded environment.
int++ is not an atomic operation, so when a thread reads its value and adds 1, another thread may read the previous value, which will raise an error.
To solve this problem, it is necessary to ensure that the addition operation is atomic, and we could use synchronization technology to do this before JDK1.5. To JDK1.5, the java.util.concurrent.atomic package provides int and long types of loading classes, which can automatically ensure that they are atomic for their operations and do not require synchronization.
2. What is the Lock interface in the Java Concurrency API? What are the advantages of comparing synchronization?
The Lock interface provides more scalable lock operation than the synchronization method and synchronization block. They allow for more flexible structures, can have completely different properties, and can support conditional objects of multiple related classes.
Its advantages are:
It can make the lock more fair, so that the thread responds to interrupts while waiting for the lock, so that the thread can try to acquire the lock, and return immediately when it cannot acquire the lock or wait for a period of time, which can be acquired and released in different orders in different ranges.
3. What is the Executors framework?
The Executor framework is introduced in Java 5 with the java.util.concurrent.Executor interface. The Executor framework is a framework that executes asynchronous tasks that execute policy calls, schedules, executes and controls according to a set of policies.
Unlimited creation threads can cause application memory overflow. So creating a thread pool is a better solution because the number of threads can be limited and the number of threads can be recycled and reused. Using the Executors framework can easily create a thread pool. Read this article to learn how to use the Executor framework to create a thread pool.
4. What is a blocking queue? How to implement a producer-consumer model using blocking queues?
The feature of java.util.concurrent.BlockingQueue is: when the queue is empty, the operation of obtaining or deleting elements from the queue will be blocked, or when the queue is full, the operation of adding elements to the queue will be blocked.
The blocking queue does not accept null values, and when you try to add null values to the queue, it throws a NullPointerException.
The implementation of blocking queues is thread-safe, and all query methods are atomic and use internal locks or other forms of concurrent control.
The BlockingQueue interface is part of the java collections framework, which is mainly used to implement producer-consumer issues.
5. What are Callable and Future?
Java 5 introduces the java.util.concurrent.Callable interface in the concurrency package. It is very similar to the Runnable interface, but it can return an object or throw an exception.
The Callable interface uses generics to define its return type. The Executors class provides some useful methods to execute tasks within a Callable in a thread pool. Since the Callable task is parallel, we have to wait for the result it returns. The java.util.concurrent.Future object solves this problem for us. After the thread pool submits the Callable task, a Future object is returned. Using it, we can know the status of the Callable task and get the execution result returned by the Callable. Future provides a get() method that allows us to wait for the Callable to end and get its execution result.
6. What is FutureTask?
FutureTask is a basic implementation of Future, we can use it with Executors to handle asynchronous tasks. Usually we don't need to use the FutureTask class, it becomes very useful just when we plan to rewrite some methods of the Future interface and keep the original basic implementation. We can just inherit from it and rewrite the methods we need.
7. What is the implementation of concurrent containers?
Java collection classes all fail quickly, which means that when the set is changed and a thread uses the iterator to traverse the set, the iterator's next() method will throw a ConcurrentModificationException exception.
Concurrent containers support concurrent traversal and concurrent updates.
The main classes are ConcurrentHashMap, CopyOnWriteArrayList and CopyOnWriteArraySet. Read this article to learn how to avoid ConcurrentModificationException.
8. What is the Executors class?
Executors provides some tooling methods for Executor, ExecutorService, ScheduledExecutorService, ThreadFactory and Callable classes.
Executors can be used to conveniently create thread pools.
In fact, there are many more basic Java interview questions, and you can organize them systematically.
I hope everyone will be successful in the interview!