Home  >  Article  >  Java  >  Java multi-threading interview questions worth collecting (with answers)

Java multi-threading interview questions worth collecting (with answers)

青灯夜游
青灯夜游forward
2019-11-25 15:21:582109browse

This article summarizes some Java multi-threading interview questions and answers for you. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to everyone.

Java multi-threading interview questions worth collecting (with answers)

What is a thread?

Thread is the smallest unit that the operating system can perform operation scheduling. It is included in the process and is the actual operating unit in the process. Programmers can use it for multi-processor programming, and you can use multi-threading to speed up computationally intensive tasks. For example, if it takes 100 milliseconds for one thread to complete a task, then it only takes 10 milliseconds to use ten threads to complete the task. Java provides excellent support for multi-threading at the language level, which is also a good selling point.

2) What is the difference between thread and process?

Threads are 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 memory space. Don't confuse this with stack memory. Each thread has its own stack memory to store local data.

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 called Runnable interface, you can inherit the java.lang.Thread class or directly call the Runnable interface to override it. Write the run() method to implement threads.

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? When is it used? 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 from other classes, of course you have to call the Runnable interface.

6) What is the difference between the 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 thread model. The start() method is used to start a newly created thread, and start() internally calls the run() method, which has a different effect than 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 a new thread.

7) What is the difference between Runnable and Callable in Java?

Runnable and Callable both represent tasks to be executed in different threads. Runnable has been available since JDK1.0, and Callable was added in JDK1.5. The main difference between them is that Callable's call() method can return values ​​and throw exceptions, while Runnable's run() method does not have these functions. Callable can return a Future object loaded with calculation results.

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.

9) What is the Java memory model?

The Java memory model specifies and guides Java programs to behave deterministically across different memory architectures, CPUs, and operating systems. It is especially important in multi-threaded situations. The Java memory model provides a guarantee that changes made by one thread can be visible to other threads, and there is a precedence relationship between them. This relationship defines some rules to make programmers think more clearly when programming concurrently. For example, the look-ahead relationship ensures that:

  • The code in the thread can be executed in order. This is called a program order rule.
  • For the same lock, an unlocking operation must occur before another locking operation that occurs later in time, also called a monitor locking rule.
  • The previous volatile write operation precedes the next volatile read operation, also called the volatile variable rule.
  • Any operation within a thread must be called after the start() call of this thread, also called a thread startup rule.
  • All operations of a thread will occur before the thread is terminated, according to the thread termination rule.
  • The termination operation of an object must be completed after the object is constructed, also called object termination rule.
  • Transitability

I strongly recommend that you read Chapter 16 of "Java Concurrent Programming Practice" to deepen your understanding of the Java memory model.

10) What are volatile variables in Java?

volatile is a special modifier that can only be used by member variables. In the absence of synchronization classes in Java concurrent programs, multi-threaded operations on member variables are transparent to other threads. Volatile variables can guarantee that the next read operation will occur after the previous write operation, which is the volatile variable rule in the previous question.

11) What is thread safety? Is Vector a thread-safe class?

If there are multiple threads running at the same time in the process where your code is located, these threads may run this code at the same time. If the results of each run are the same as those of single-threaded runs, and the values ​​of other variables are the same as expected, it is thread-safe. A thread-safe counter class will not cause calculation errors when the same instance object is used by multiple threads. Obviously you can divide collection classes into two groups, thread-safe and non-thread-safe. Vector uses synchronized methods to achieve thread safety, while ArrayList, which is similar to it, is not thread safe.

12) What is a race condition in Java? Give an example.

Race conditions will cause some bugs in the program under concurrent conditions. Race conditions will occur when multiple threads compete for some resources. If the program to be executed first fails to compete and is executed later, then some uncertain bugs will appear in the entire program. Such bugs are difficult to find and recur due to random competition between threads.

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 they were deprecated in subsequent JDK versions due to potential deadlock threats. After that, the designers of the Java API did not provide a Compatible and thread-safe way to stop a thread. The thread will automatically end when the run() or call() method is executed. If you want to manually end a thread, you can use a volatile Boolean variable to exit the run() method's loop or cancel the task to interrupt the thread.

14) What happens if an exception occurs while 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 used to handle sudden thread interruption caused by uncaught exceptions. When an uncaught exception will cause a thread to be interrupted, 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 achieve this through shared objects, or use concurrent data structures like blocking queues. This tutorial "Java Inter-Thread Communication" (involving 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 question, because multiple threads can wait for a single monitoring lock. The designers of the Java API provide some methods to notify them when the waiting conditions change, but these methods are not fully implemented. . The notify() method cannot wake up a specific thread, so it is only useful when a thread is waiting. And notifyAll() wakes up all threads and allows them to compete for the lock to ensure that at least one thread can continue to run.

17) Why are the wait, notify and notifyAll methods not in the thread class?

This is a design-related question that examines the interviewer's views on existing systems and some common but seemingly unreasonable things. When answering these questions, you need to explain why it makes sense to put these methods in the Object class, and why not to put them in the Thread class. An obvious reason is that the locks provided by JAVA are at the object level rather than at the thread level. Each object has a lock and is obtained through the thread. If the thread needs to wait for some lock then it makes sense to call the wait() method in the object. If the wait() method is defined in the Thread class, it is not 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 locks belong to objects.

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 race conditions are completely eliminated. It's a good way to get thread safety for objects that are expensive to create, for example you can use ThreadLocal to make SimpleDateFormat thread safe, since that class is expensive to create and requires creating a different instance for each call so it's not worth having in local scope Using it, if each thread is provided with its own unique copy of the variable, the efficiency will be greatly improved. First, the number of expensive objects created is reduced through reuse. Second, you gain thread safety without using expensive synchronization or immutability. Another good example of thread-local variables is the ThreadLocalRandom class, which reduces the number of costly Random objects to create in a multi-threaded environment.

19) What is FutureTask?

In Java concurrent programs, FutureTask represents an asynchronous operation that can be canceled. It has methods such as starting and canceling operations, querying whether operations are completed, and retrieving operation results. The result can only be retrieved when the operation is completed. If the operation has not been 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 status and the latter will not. The interrupt mechanism of Java multi-threading is implemented using internal flags. Calling Thread.interrupt() to interrupt a thread will set the interrupt flag to true. When the interrupt thread calls the static method Thread.interrupted() to check the interrupt status, the interrupt status will be cleared. The non-static method isInterrupted() is used to query the interrupt status of other threads and does not change the interrupt status identifier. Simply put, any method that throws InterruptedException will clear the interrupt status. In any case, the interrupt status of a thread may be changed by other threads calling interrupts.

21) Why are the wait and notify methods called in synchronized blocks?

Mainly because the Java API mandates this. If you don't do this, your code will throw an IllegalMonitorStateException. Another reason is to avoid race conditions between wait and notify.

22) Why should you check wait conditions in a loop?

Threads in a wait state may receive false alerts and spurious wakeups if not checked in a loop Waiting for a condition, the program will exit if the end condition is not met. Therefore, when a waiting thread wakes up, its original waiting state cannot be considered to be still valid. It may change during the period after the notify() method is called and before the waiting thread wakes up. This is why using the wait() method in a loop works better. You can create a template in Eclipse to call wait and notify to try it. If you want to learn more about this issue, I recommend reading the threads and synchronization chapter in the book "Effective Java".

23) What is the difference between synchronized collections and concurrent collections in Java?

Both synchronized collections and concurrent collections provide suitable thread-safe collections for multi-threading and concurrency, but concurrent collections are more scalable. Before Java 1.5, programmers could only use synchronized collections, which would cause contention during multi-thread concurrency and hinder the scalability of the system. Java5 introduced concurrent collections like ConcurrentHashMap, which not only provide thread safety but also improve scalability with modern techniques such as lock separation and internal partitioning.

24) What is the difference between heap and stack in Java?

Why is this question classified as a multi-threading and concurrency interview question? Because the stack is a memory area closely related to threads. Each thread has its own stack memory, which is used to store local variables, method parameters and stack calls. Variables stored in one thread are not visible 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 it from the heap to its own stack. If multiple threads use this variable, it may cause problems. At this time, volatile variables can come into play. It requires the thread to start from the main stack. Read the value of a variable from memory.

25) What is a thread pool? Why use it?

Creating threads costs expensive resources and time. If threads are created only when a task comes, the response time will become longer, and the number of threads that can be created by a process is limited. In order to avoid these problems, several threads are created to respond to processing when the program starts. They are called thread pools, and the threads inside are called worker threads. Starting from JDK1.5, the Java API provides the Executor framework so that you can create different thread pools. For example, a single thread pool processes one task at a time; a fixed number of thread pools or a cache thread pool (an extensible thread pool suitable for programs with many short-lived tasks).

26) How to write code to solve the producer-consumer problem?

In reality, many of the threading problems you solve belong to the producer-consumer model, where one thread produces tasks for other threads to consume. You must know how to communicate between threads to solve this problem. The lower-level method is to use wait and notify to solve this problem. The better method is to use Semaphore or BlockingQueue to implement the producer-consumer model. This tutorial implements it.

27) How to avoid deadlock?


Deadlock in Java multi-threading
Deadlock refers to a situation caused by two or more processes competing for resources during execution. The phenomenon of waiting for each other will not be able to advance without external force. This is a serious problem, because a deadlock will cause your program to hang and be unable to complete the task. The following four conditions must be met for a deadlock to occur:

  • Mutual exclusion conditions: One resource can only Can be used by a process.
  • Request and hold conditions: When a process is blocked due to requesting resources, it will keep the obtained resources.
  • Non-deprivation conditions: Resources that a process has obtained cannot be forcibly deprived of them before they are used up.
  • Loop waiting conditions: A head-to-tail loop waiting for resources relationship is formed between several processes.

The simplest way to avoid deadlock is to prevent circular waiting conditions, set flags and sort all resources in the system, and stipulate that all processes must apply for resources in a certain order (ascending or descending order) Do operations to avoid deadlock.

28) What is the difference between livelock and deadlock in Java?

This is an extension of the above question. Livelock is similar to deadlock. The difference is that the state of the thread or process in livelock is constantly changing. Livelock can be considered a special kind of hunger. A realistic example of livelock is when two people meet in a narrow corridor. Both people try to avoid each other so that each other can pass, but because the avoidance directions are the same, no one can pass through the corridor in the end. Simply put, the main difference between livelock and deadlock is that in the former, the state of the process can change but it cannot continue to execute.

29) How to detect whether a thread owns a lock?

I never knew that we could detect whether a thread owns a lock until I participated in a phone interview. There is a method in java.lang.Thread called holdsLock(), which returns true if and only if the current thread holds a lock on a specific object.

30) How do you get the thread stack in Java?

There are multiple ways to obtain the thread stack of a Java process for different operating systems. When you get the thread stack, the JVM will save the status of all threads to a log file or output to the console. In Windows you can use the Ctrl Break key combination to get the thread stack, and in Linux use the kill -3 command. You can also use the jstack tool to obtain it, which operates on the thread ID. You can use the jps tool to find the ID.

31) Which parameter in JVM is used to control the stack size of the thread?

This question is very simple. The -Xss parameter is used to control the stack size of the thread.

32) What is the difference between synchronized and ReentrantLock in Java?

Java has been able to achieve mutual exclusion only through the synchronized keyword for a long time in the past, which has some shortcomings. For example, you cannot extend methods or block boundaries outside the lock, you cannot cancel midway when trying to acquire the lock, etc. Java 5 provides more complex control through the Lock interface to solve these problems. The ReentrantLock class implements Lock, which has the same concurrency and memory semantics as synchronized but is also extensible.

33) There are three threads T1, T2, and T3. How to ensure that they are executed in order?

In multi-threading, there are many ways to let threads execute in a specific order. You can use the join() method of the thread class to start another thread in one thread, and the other thread completes the thread and continues. implement. To ensure the order of the three threads you should start the last one first (T3 calls T2, T2 calls T1), so that T1 will finish first and T3 will finish last.

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 guarantees that the current thread will give up the CPU occupation and does not guarantee that other threads will be able to occupy the CPU. The thread executing yield() may be executed again immediately after entering the paused state.

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 of the ConcurrentHashMap class constructor with a default value of 16 to avoid contention in multi-threaded situations.

36) What is Semaphore in Java?

Semaphore in Java is a new synchronization class, which is a counting signal. Conceptually, a semaphore maintains a permissioned collection. If necessary, each acquire() blocks until the permission is available, and then acquires the permission. Each release() adds a permission, thereby potentially releasing a blocking acquirer. However, instead of using actual license objects, Semaphore only counts the number of available licenses and takes appropriate action. Semaphores are often used in multi-threaded code, such as database connection pools.

37) If the thread pool queue is full when you submit the task. What happens when the meeting happens?

This is a tricky question, and many programmers will think that the task will block until there is space in the thread pool queue. In fact, if a task cannot be scheduled for execution, ThreadPoolExecutor’s submit() method will throw a RejectedExecutionException.

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 the execute() method is void, which is defined in the Executor interface, and the submit() method can return a Future holding the calculation results. Object, which is defined in the ExecutorService interface, which extends the Executor interface. Other thread pool classes like ThreadPoolExecutor and ScheduledThreadPoolExecutor have these methods.

39) What is blocking method?

The blocking method means that the program will wait for the method to complete without doing anything else. The accept() method of ServerSocket is to wait for the client to connect. Blocking here means that before the call result is returned, the current thread will be suspended 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.

40) Is Swing thread-safe? Why?

You can answer with certainty that Swing is not thread-safe, but you should explain the reason for your answer even if the interviewer does not ask you why. When we say that swing is not thread-safe, we often mention its components. These components cannot be modified in multi-threads. All updates to GUI components must be completed in the AWT thread, and Swing provides two callback methods: synchronous and asynchronous. to update.

41) 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() synchronously updates GUI components, such as a progress bar. Once the progress is updated, the progress bar must also change accordingly. If the progress is tracked by multiple threads, then call the invokeAndWait() method to request the event dispatch thread to update the component accordingly. The invokeLater() method calls the update component asynchronously.

42) Which methods in Swing API are thread-safe?

This question also mentioned swing and thread safety. Although the component is not thread-safe, there are some methods that can be safely called by multiple threads, such as repaint(), revalidate(). JTextComponent's setText() method and JTextArea's insert() and append() methods are also thread-safe.

43) How to create Immutable object in Java?

This problem seems to have nothing to do with multi-threading, but immutability can help simplify already complex concurrent programs. Immutable objects can be shared without synchronization, reducing the synchronization overhead for concurrent access to the object. However, Java does not have the @Immutable annotation. To create an immutable class, you must implement the following steps: initialize all members through the constructor method, do not provide setter methods for variables, and declare all members as private, so that direct access is not allowed. When accessing these members, 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 a detailed tutorial. After reading it, you can be confident.

44) What is ReadWriteLock in Java?

Generally speaking, read-write locks are the result of lock separation technology used to improve the performance of concurrent programs. 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 writing thread, a read lock may be held by multiple reading threads at the same time. Write locks are exclusive. You can use ReentrantReadWriteLock in the JDK to implement this rule. It supports up to 65535 write locks and 65535 read locks.

45) What is a busy loop in multi-threading?

Busy loop is when the programmer uses a loop to make a thread wait, unlike the traditional methods of wait(), sleep () or yield() they all give up CPU control, and the busy loop does not give up the CPU, it is running an empty loop. The purpose of this is to preserve the CPU cache. In a multi-core system, a waiting thread may run on another core when it wakes up, which will rebuild the cache. It can be used in order to avoid rebuilding the cache and reduce the time waiting for rebuilding.

46) What is the difference between volatile variables and atomic variables?

This is an interesting question. First of all, volatile variables and atomic variables look similar, but their functions are different. Volatile variables can ensure a look-ahead relationship, that is, a write operation will occur before a subsequent read operation, but it does not guarantee atomicity. For example, if the count variable is modified with volatile, 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 atomically perform an increment operation to add one to the current value. Similar operations can also be performed on other data types and reference variables.

47) What happens if a thread inside a synchronized block throws an exception?

This question has troubled many Java programmers. If you can think of the clue of whether the lock is released to answer it, there is hope that you can get it right. Regardless of whether your synchronized block exits normally or abnormally, the thread inside will release the lock, so compared to the lock interface, I prefer the synchronized block because it does not require me to spend energy to release the lock. This function can be implemented by releasing the lock in the finally block.

48) What is the double check lock in singleton mode?

This question is often asked in Java interviews, but interviewers' satisfaction with answering this question is only 50%. Half of the people can't write double-check locking and half of the people can't explain its hidden dangers and how Java 1.5 corrects it. It is actually an old method used to create thread-safe singletons. When the singleton instance is first created, it attempts to use a single lock for performance optimization, but it fails in JDK1.4 because it is too complex. I personally don't like it either. Anyway, even if you don't like it it's worth knowing it because it's often asked.

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 locking and the interviewer asks about alternatives to creating a Singleton class, you can use the JVM's class loading and static variable initialization features to create Singleton instances, or using enumeration types to create Singletons, I like this method.

50) Write 3 multi-threading best practices that you follow

This kind of question is my favorite, I believe you are writing concurrent code to improve performance Certain best practices will also be followed. Here are three best practices that I think most Java programmers should follow:

  • Give your threads a meaningful name.
    This makes it easier to find bugs or track. OrderProcessor, QuoteProcessor or TradeProcessor are much better names 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 JDK follow this best practice.
  • Avoid locking and reduce the scope of synchronization
    Locks are expensive and context switching takes more time and space. Try to use synchronization and locks to a minimum to reduce the critical section. Therefore I prefer synchronized blocks to synchronized methods, it gives me absolute control over the lock.
  • Use more synchronization classes and less use of wait and notify
    First of all, synchronization classes such as CountDownLatch, Semaphore, CyclicBarrier and Exchanger simplify coding operations, but it is difficult to control complex control flow using wait and notify. Secondly, these classes are written and maintained by the best companies. They will be continuously optimized and improved in subsequent JDKs. Using these higher-level synchronization tools, your program can be optimized effortlessly.
  • Use more concurrent collections and less use of synchronized collections
    This is another best practice that is easy to follow and has huge benefits. Concurrent collections are more scalable than synchronized collections, so use concurrent collections when programming concurrently. Better results. If you need to use map next time, you should first think of using ConcurrentHashMap.

51) How to force start a thread?

This question is like how to force Java garbage collection. There is currently no method. Although you can use System.gc() to perform garbage collection, there is no guarantee of success. There is no way to force start a thread 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 appeared in JDK7, through which Java developers can take full advantage of multi-processors on modern servers. It is specially designed for applications that can be recursively divided into many sub-modules in order to use all available processing power to improve program performance. A huge advantage of the fork join framework is that it uses a work-stealing algorithm. Worker threads that can complete more tasks can steal tasks from other threads for execution.

53) What is the difference between calling wait() and sleep() methods in Java multi-threading?

Both wait and sleep in Java programs will cause some form of pause, and they 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 will release the lock, while the sleep() method only releases CPU resources or stops the current thread for a period of time, but does not release the lock.

For more Java-related interview knowledge, please visit the java interview questions column!

The above is the detailed content of Java multi-threading interview questions worth collecting (with answers). For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:segmentfault.com. If there is any infringement, please contact admin@php.cn delete