Below are popular interview questions related to Java threads, you can use them to prepare for the interview.
1) What is a thread?
A thread is the smallest unit that the operating system can perform operations and scheduling. It is contained in the process and is the actual operating unit in the process. Programmers can program multiprocessors through it, and you can speed up operation-intensive tasks using multithreading. For example, if it takes 100 milliseconds for a thread to complete a task, it takes only 10 milliseconds for a thread to complete the task change using ten 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 a thread and a process?
Threads are subsets of processes. A process can have many threads, and each thread performs different tasks in parallel. Different processes use different memory spaces, while all threads share the same memory space. Don't mess it with stack memory, each thread has a separate stack memory for storing local data. For more details, please click here.
3) How to implement threads in Java?
There are two ways at the language level. An instance of the java.lang.Thread class is a thread, but it needs to call the java.lang.Runnable interface to execute. Since the thread class itself is the Runnable interface called, you can inherit the java.lang.Thread class or directly call the Runnable interface to override the run () method to implement the thread. For more details, please click here.
4) Use Runnable or Thread?
This question is a follow-up to the previous question. Everyone knows that we can implement threads by inheriting the Thread class or calling the Runnable interface. The question is, which method is better? Under what circumstances should I use it? This question is easy to answer if you know that Java does not support multiple inheritance of classes, but allows you to call multiple interfaces. So if you want to inherit other classes, of course, it is better to call the Runnable interface. For more details, please click here.
6) What is the difference between start () and run () methods in the Thread class?
This question is often asked, but it can still distinguish the interviewer's understanding of the Java threading model from this. The start () method is used to start the newly created thread, and the run () method is called internally, which is different from the effect of directly calling the run () method. When you call the run () method, it will only be called in the original thread. If no new thread is started, the start () method will start the new thread. For more discussions, please click here
7) What is the difference between Runnable and Callable in Java?
Both Runnable and Callable represent tasks to be executed in different threads. Runnable has been available since JDK1.0, and Callable has been added in JDK1.5. Their main difference is that the call() method of Callable can return values and throw exceptions, while the run() method of Runnable does not have these functions. Callable can return a Future object loaded with the calculation results. My blog has more detailed instructions.
8) What is the difference between CyclicBarrier and CountDownLatch in Java?
Both CyclicBarrier and CountDownLatch can be used to make a group of threads wait for other threads. Unlike CyclicBarrier, CountdownLatch cannot be reused. Click here to see more information and sample code.
9) What is the Java memory model?
The Java memory model specifies and guides Java programs to behave deterministically between different memory architectures, CPUs, and operating systems. It is especially important in multi-threading situations. The Java memory model can ensure that the changes made by one thread are visible to other threads, and relationships occur first. This relationship defines some rules to make programmers clearer in their concurrent programming. For example, having a relationship first ensures:
Code within threads can be executed in sequence, which is called program order rules.
For the same lock, an unlocking operation must occur before another lock operation that occurs in time, which is also called the management locking rule.
The previous write operation to a Volatile is before the next read operation of a volatile, which is also called the volatile variable rule.
Any operation within a thread must be called after the start () of this thread, also known as the thread start rule.
All operations of a thread will be terminated before the thread terminates.
The termination operation of an object must be after the object is constructed, which is also called the object termination rule.
Transitive
I strongly recommend that you read Chapter 16 of "Java Concurrency Programming Practice" to deepen your understanding of Java memory model.
10) What is the volatile variable in Java?
volatile is a special modifier that can only be used by member variables. In the case where Java concurrent programs lack synchronous classes, multithreading operations on member variables are transparent to other threads. The volatile variable can ensure that the next read operation will occur after the previous write operation, which is the volatile variable rule of the previous question. Click here to see more volatile related content.
11) What is thread safety? Is Vector a thread-safe class? (See here for details)
If your code is in the process where you are in, there are multiple threads running at the same time, and these threads may run this code at the same time. If the result of each run is the same as the result of a single thread run, and the values of other variables are the same as expected, it is thread-safe. The same instance object of a thread-safe counter class will not cause calculation errors when used by multiple threads. Obviously you can divide the collection class into two groups, thread-safe and non-thread-safe. Vector uses synchronization methods to achieve thread-safety, while ArrayList similar to it is not thread-safe.
12) What are race conditions in Java? Give an example.
Race conditions will cause some bugs to occur in concurrent situations of the program. When multi-threading competes for some resources, race conditions will arise. If the first program to be executed fails and is later executed, some uncertain bugs will appear in the entire program. Such bugs are difficult to detect and recur because of random competition between threads. An example is disordered processing, see the answer for details.
13) How to 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 due to potential deadlock threats, they were deprecated in subsequent JDK versions. After that, the designer of the Java API did not provide a compatible and thread-safe way to stop a thread. When the run () or call () method is executed, the thread will automatically end. If you want to end a thread manually, you can use the volatile boolean variable to exit the run () method loop or cancel the task to interrupt the thread. Click here to view the sample code.
14) What happens when an exception occurs when a thread is running?
This is a very tricky Java interview question I encountered in an interview. Simply put, if the exception is not caught, the thread will stop executing.
Thread.UncaughtExceptionHandler is an embedded interface for handling uncaught exceptions that cause sudden thread interruption. When an uncaught exception causes a thread to interrupt, the JVM will use Thread.getUncaughtExceptionHandler () to query the thread's UncaughtExceptionHandler and pass the thread and exception as parameters to the handler's uncaughtException () method for processing.
15) How to share data between two threads?
You can do this by sharing objects, or use concurrent data structures like blocking queues. This tutorial, "Java Inter-Thread Communication" (which involves sharing objects between two threads) uses the wait and notify methods to implement the producer consumer model.
16) What is the difference between notify and notifyAll in Java?
This is another tricky problem, because multithreading can wait for single monitoring locks, and Java API designers provide some ways to notify them when waiting for conditions to change, but these methods are not fully implemented. The notify () method cannot wake up a specific thread, so it will only work when one thread is waiting. And notifyAll() wakes up all threads and allows them to compete for locks to ensure that at least one thread can continue to run. My blog has more detailed information and sample code.
17) Why are wait, notify and notifyAll methods not in the thread class?
This is a design-related question that examines the interviewer's perception of existing systems and something that is common but seems unreasonable. When answering 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, obtained through threads. If the thread needs to wait for some locks, it makes sense to call the wait() method in the object. If the wait() method is defined in the Thread class, it will not be obvious which lock the thread is waiting for. Simply put, since wait, notify and notifyAll are lock-level operations, they are defined in the Object class because the lock belongs to the object. You can also check out this article to learn more.
18) What is a ThreadLocal variable?
ThreadLocal is a special variable in Java. Each thread has a ThreadLocal, which means that each thread has its own independent variable, and the race conditions are completely eliminated. It is a great way to get thread-safe for creating expensive objects. For example, you can use ThreadLocal to make SimpleDateFormat thread-safe because that class is expensive to create and requires creating a different instance for each call, so it is not worth using it locally. If you provide each thread with a unique copy of variables, it will greatly improve efficiency. First, the number of expensive objects created is reduced by multiplexing. Second, you gain thread safety without using costly synchronization or invariance. Another good example of thread local variables is the ThreadLocalRandom class, which reduces the number of expensive Random objects created in a multi-threaded environment. See the answers to learn more.
19) What is FutureTask?
In a Java concurrent program, FutureTask represents an asynchronous operation that can be cancelled. It has methods such as starting and canceling operations, querying whether the operations are completed and retrieving the operation results. The result can only be retrieved when the operation is completed. If the operation has not completed, the get method will block. A FutureTask object can wrap objects that call Callable and Runnable. Since FutureTask also calls the Runnable interface, it can be submitted to the Executor for execution.
20) What is the difference between interrupted and isInterruptedd methods in Java?
The main difference between interrupted () and isInterrupted () is that the former will clear the interrupt state while the latter will not. The interrupt mechanism of Java multithreading is implemented with internal identifiers. Calling Thread.interrupt () to interrupt a thread will set the interrupt identifier to true. When the interrupt thread calls the static method Thread.interrupted() to check the interrupt state, the interrupt state will be cleared. The non-static method isInterrupted () is used to query the interrupt status of other threads without changing the interrupt status identifier. Simply put, any method that throws an InterruptedException will clear the interrupt state. In any case, the interrupt state of a thread may be changed by other threads calling interrupts.
21) Why do wait and notify methods need to be called in a synchronous block?
This is mainly because the Java API forces this, and if you don't, your code will throw an IllegalMonitorStateException exception. Another reason is to avoid race conditions between wait and notify.
22) Why should you check the waiting conditions in the loop?
Threads in waiting state may receive error alerts and pseudo-wakes. If the waiting condition is not checked in the loop, the program will exit without meeting the end condition. Therefore, when a waiting thread wakes up, it cannot be considered that its original waiting state is still valid, and it may change during this period after the notify() method call and before the waiting thread wakes up. This is why using the wait() method in a loop works better, you can create templates in Eclipse to call wait and notify and give it a try. If you want to learn more about this issue, I recommend you to read the threading and synchronization chapters in the book "Effective Java".
23) What is the difference between synchronous collections and concurrent collections in Java?
Both synchronous collections and concurrent collections provide suitable thread-safe collections for multithreading and concurrency, but concurrent collections are more scalable. Before Java 1.5, programmers only used synchronous collections, and when multi-threaded concurrency was contributing, it would lead to contention, hindering the scalability of the system. 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 zones. See the answer for more details.
24) What is the difference between heap and stack in Java?
Why is this question classified in multi-threaded and concurrent interview questions? Because the stack is a memory area closely related to the thread. Each thread has its own stack memory, which is used to store local variables, method parameters and stack calls. The variables stored in one thread are invisible to other threads. The heap is a common memory area shared by all threads. Objects are created in the heap. In order to improve efficiency, the thread will cache a from the heap to its own stack. If multiple threads use this variable, it may cause problems. At this time, the volatile variable can play a role, which requires the thread to read the value of the variable from the main memory.
See the answer for more details.
25) What is a thread pool? Why use it?
Creating threads takes expensive resources and time. If a thread is created only after the task comes, the response time will become longer, and a process can create a limited number of threads. To avoid these problems, several threads are created to respond and process when the program is started. They are called thread pools, and the threads inside are called worker threads. Starting with JDK1.5, the Java API provides the Executor framework that allows you to create different thread pools. For example, a single thread pool, which handles one task at a time; a fixed number of thread pools or cache thread pools (an extensible thread pool suitable for many programs with short-lived tasks). See this article for more details.
26) How to write code to solve the producer and consumer problems?
In reality, many of the thread problems you solve belong to the producer consumer model, which is that one thread production task is for consumption by other threads. You must know how to communicate between threads to solve this problem. The relatively low-level method is to use wait and notify to solve this problem. The more excellent method is to use Semaphore or BlockingQueue to implement the producer and consumer model. This tutorial implements it.
27) How to avoid deadlocks?
Deadlock in Java multithreading
Deadlock refers to a phenomenon of mutual waiting caused by two or more processes during the execution process due to the competition for resources. Without external forces, they will not be able to continue. This is a serious problem, because deadlocks will make your program suspend and unable to complete the task. The following four conditions must be met for the occurrence of deadlocks:
Mutual Exclusion Condition: A resource can only be used by one process at a time.
Request and hold conditions: When a process blocks due to requesting resources, it keeps the acquired resources.
Conditions for not depriving: The resources obtained by the process cannot be forcibly deprived until the end of use.
Loop waiting conditions: A loop waiting resource relationship is formed between several processes that are connected in head and tail.
The easiest way to avoid deadlocks is to prevent loop waiting conditions, set flags and sort all resources in the system, and stipulate that all process application resources must be operated in a certain order (ascending or descending order) to avoid deadlocks. This tutorial has code examples and discussion details about avoiding deadlocks.
28) What is the difference between live locks and deadlocks in Java?
This is the extension of the previous question. Live locks are similar to deadlocks. The difference is that the state of the thread or process in the live lock is constantly changing. Live locks can be considered a special kind of hunger. A realistic example of a live lock is when two people meet in a narrow corridor. Both of them try to avoid each other so that each other can pass through, but because the direction of avoidance is the same, no one can pass through the corridor in the end. Simply put, the main difference between a live lock and a dead lock is that the state of the former process can be changed but cannot be continued to be executed.
29) How to detect whether a thread has a lock?
I never knew we could actually detect if a thread had a lock until I attended a telephone interview. There is a method in java.lang.Thread called holdsLock(), which returns true if and only if the current thread owns a lock for a specific object. You can check out this article to learn more.
30) How do you get thread stack in Java?
For different operating systems, there are multiple ways to get the thread stack of Java processes. When you get the thread stack, the JVM will store the state of all threads to the log file or output it to the console. In Windows, you can use the Ctrl + Break key combination to get the thread stack, and use the kill -3 command in Linux. You can also use the jstack tool to obtain it, which operates on thread ids, and you can use the jps tool to find the id.
31) Which parameter in JVM is used to control the stack of threads with a small stack
This problem is very simple, the -Xss parameter is used to control the stack size of the thread. You can view the JVM configuration list for more information on this parameter.
32) What is the difference between synchronized and ReentrantLock in Java?
Java has been able to achieve mutual exclusion for a long time through synchronized keywords, and it has some disadvantages. For example, you cannot expand methods or block boundaries other than locks, and you cannot cancel halfway when trying to acquire locks, etc. Java 5 provides more complex controls to solve these problems through the Lock interface. The ReentrantLock class implements Lock, which has the same concurrency and memory semantics as synchronized and it is also extensible. You can check out this article to learn more
33) There are three threads T1, T2, and T3. How to make sure they are executed in order?
There are many ways to enable threads to execute in a specific order in multithreading. You can use the join () method of the thread class to start another thread in one thread, and another thread completes the thread to continue execution. To ensure the order of three threads you should start the last one first (T3 calls T2, T2 calls T1), so that T1 will complete first and T3 will complete last. You can check out this article to learn more.
34) What is the function of the yield method in the Thread class?
The Yield method can pause the currently executing thread object and allow other threads with the same priority to execute. It is a static method and only ensures that the current thread gives up CPU usage and cannot guarantee that other threads can occupy the CPU. The thread executing yield () may be executed immediately after entering the paused state. Click here to see more about the yield method.
35) What is the concurrency of ConcurrentHashMap in Java?
ConcurrentHashMap divides the actual map into several parts to achieve its scalability and thread safety. This division is obtained using concurrency, which is an optional parameter to the ConcurrentHashMap class constructor, with a default value of 16, so that contention can be avoided in multithreading situations. For more concurrency and internal resizing please read my article How ConcurrentHashMap works in Java.
36) What is Semaphore in Java?
Semaphore in Java is a new synchronization class, which is a counting signal. Conceptually, conceptually, semaphore maintains a set of permits. If necessary, each acquire() will be blocked before the license becomes available before it is obtained. Each release() adds a permission, which may release a blocking acquirer. However, without using the actual license object, Semaphore only counts the available license numbers and takes corresponding actions. Semaphores are often used in multithreaded code, such as database connection pools. For more details, please click here.
37) If you submit a task, the thread pool queue is full. What happens when it happens?
This question is crafty and many programmers will think that the task will block until the thread pool queue has space. In fact, if a task cannot be scheduled to be executed, the ThreadPoolExecutor's submit() method will throw a RejectedExecutionException exception.
38) What is the difference between submit () and execute () methods in Java thread pool?
Both methods can submit tasks to the thread pool. The return type of execute() method is void, which is defined in the Executor interface, and the submit() method can return the Future object holding the calculation results. It is defined in the ExecutorService interface. It extends the Executor interface. Other thread pool classes such as ThreadPoolExecutor and ScheduledThreadPoolExecutor have these methods. For more details, please click here.
39) What is a blocking method?
A blocking method means that the program will wait for the method to complete and does not do anything else. The ServerSocket's accept () method is to wait for the client to connect. Blocking here means that the current thread will be suspended before the call result is returned and will not return until the result is obtained. In addition, there are asynchronous and non-blocking methods that return before the task is completed. For more details, please click here.
40) Is Swing thread-safe? Why?
You can give a positive answer, Swing is not thread-safe, but you should explain why this answer is even if the interviewer didn't ask you why. When we say swing is not thread-safe, it often mentions its components, which cannot be modified in multi-threaded. All updates to GUI components must be completed in AWT threads. Swing provides two synchronous and asynchronous callback methods to update. Click here to see more swing and thread safety related content.
41) What is the difference between invokeAndWait and invokeLater in Java?
These two methods are provided by the Swing API to Java developers for updating GUI components from the current thread rather than the event dispatch thread. InvokeAndWait () synchronously updates GUI components, such as a progress bar. Once the progress is updated, the progress bar must also be changed accordingly. If the progress is tracked by multiple threads, then the invokeAndWait () method is called to request the event dispatch thread to update the component accordingly. The invokeLater () method is called asynchronously to update the component. For more details, please click here.
42) What methods in the Swing API are thread-safe?
This question also mentions swing and thread safety. Although components are not thread-safe, there are some methods that can be called multi-threadably, such as repaint () and revalidate (). The setText() method of JTextComponent and the insert () and append () methods of JTextArea are also thread-safe.
43) How to create an Immutable object in Java?
This problem seems to have nothing to do with multi-threading, but invariance helps simplify already complex concurrent programs. Immutable objects can be shared without synchronization, reducing the synchronization overhead when concurrent access to the object. However, Java does not have the @Immutable annotation. To create an immutable class, we need to implement the following steps: initialize all members through a constructor, do not provide a setter method to the variable, and declare all members as private, so that these members are not allowed to be directly accessed. In the getter method, do not directly return the object itself, but clone the object and return a copy of the object. My article how to make an object Immutable in Java has detailed tutorials, and you can be full of confidence after reading it.
44) What is ReadWriteLock in Java?
Generally speaking, read and write locks are the result of lock separation technology used to improve the performance of concurrent programs. ReadWriteLock in Java is a new interface added in Java 5. A ReadWriteLock maintains a pair of associated locks, one for read-only operations and one for writes. A read lock may be held by multiple read threads at the same time without a write thread. Write locks are exclusive, you can implement this rule using ReentrantReadWriteLock in JDK, which supports up to 65535 write locks and 65535 read locks.
45) What is a busy loop in multithreading?
Busy loops are when programmers use loops to make a thread wait. Unlike traditional methods such as wait(), sleep() or yield(), they all give up CPU control, while busy loops do not give up CPU, it is just running an empty loop. The purpose of this is to preserve the CPU cache. In a multi-core system, one waiting for a thread to wake up may run in another kernel, which will rebuild the cache. It is available to avoid rebuilding the cache and reduce the time waiting for rebuilding. You can check this article for more information.
46) What is the difference between volatile variables and atomic variables?
This is an interesting question. First, the volatile variable looks very similar to the atomic variable, but the functions are different. The Volatile variable ensures a predecessor relationship, that is, write operations will occur before subsequent read operations, but it does not guarantee atomicity. For example, modifying the count variable with volatile, then the count++ operation is not atomic. The atomic method provided by the AtomicInteger class can make this operation atomic. For example, the getAndIncrement() method will perform atomic increment operations to add the current value by one, and other data types and reference variables can also perform similar operations.
47) What happens if a thread within a synchronization block throws an exception?
This question has tricked many Java programmers. If you can think of whether the lock releases this clue to answer, you still hope to answer it correctly. No matter whether your synchronization block exits normally or abnormally, the threads inside will release the lock, so I prefer the synchronization block compared to the lock interface because it does not require me to spend my energy to release the lock. This function can be implemented by releasing the lock in finally block.
48) What is the double check lock in singleton mode?
This question is often asked in Java interviews, but the interviewer is only 50% satisfied with answering this question. Half of people can't write a double check lock and half of people can't tell it's hidden dangers and how Java 1.5 corrected it. It is actually an old method to create thread-safe singletons. When a singleton instance is first created, it tries to optimize performance with a single lock, but because it is too complex, it fails in JDK1.4, and I personally don't like it either. Anyway, even if you don't like it, you still have to understand it because it is often asked. You can check out how double checked locking on Singleton works article for more information.
49) How to create a thread-safe Singleton in Java?
This is a follow-up to the above question. If you don't like double check locks and the interviewer asked about an alternative method to create a Singleton class, you can use the JVM class loading and static variable initialization features to create a Singleton instance, or use enumeration types to create a Singleton. I like this method. You can check this article for more information.
50) Write 3 multithreading best practices you follow
I like this kind of problem the most, and I believe you will follow certain best practices when writing concurrent code to improve performance. Here are three best practices I think most Java programmers should follow:
Give your thread a meaningful name.
This makes it easy to find bugs or track them. OrderProcessor, QuoteProcessor or TradeProcessor This name is much better than Thread-1. Thread-2 and Thread-3. Give the thread a name related to the task it wants to complete. All major frameworks and even JDKs follow this best practice.
Avoid locking and narrowing the scope of synchronization
Locks are expensive and context switching is more time-consuming. Try using synchronization and locks to minimize the critical area. So I prefer the synchronization blocks over the synchronization method, which gives me absolute control over the lock.
Use more synchronization classes and use less wait and notify
First, CountDownLatch, Semaphore, CyclicBarrier and Exchanger synchronous classes simplify coding operations, while it is difficult to control complex control flows with wait and notify. Secondly, these classes are written and maintained by the best enterprises. They will continue to be optimized and improved in subsequent JDKs. Using these higher-level synchronization tools, your program can be optimized without any effort.
Use more concurrent sets and less synchronized sets. This is another easy-to-follow best practice. Concurrent sets are more scalable than synchronized sets, so using concurrent sets is better for concurrent programming. If you need to use map next time, you should first think of using ConcurrentHashMap. My article Java concurrent collections have a more detailed description.
51) How to force startup of a thread?
This problem is like how to force Java garbage collection. There is no way to do it yet. Although you can use System.gc () to perform garbage collection, it is not guaranteed to be successful. There is no way to force a thread to start in Java, it is controlled by the thread scheduler and Java does not publish the relevant API.
52) What is the fork join framework in Java?
The fork join framework is an efficient tool that emerged in JDK7, through which Java developers can make the most of the multiprocessors on modern servers. It is designed specifically for those that can be recursively divided into many submodules, with the goal of using all available processing power to improve the performance of the program. A huge advantage of the fork join framework is that it uses a work-stealing algorithm, and worker threads that can complete more tasks can steal tasks from other threads to execute. You can check this article for more information.
53) What is the difference between calling wait() and sleep() methods in Java multithreading?
Wait and sleep in Java programs both cause some form of pause, which can meet different needs. The wait() method is used for inter-thread communication. If the wait condition is true and other threads are awakened, it releases the lock, while the sleep() method only releases CPU resources or allows 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.