Java Multithreading and Concurrency Basics Interview Questions and Answers

                   Java Multithreading and Concurrency Basics Interview Questions and Answers

  Original link: http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-answers/

  The question of multithreading and concurrency is one of the more frequently asked questions in Java technical interviews. Here, most of the important questions are listed from an interview point of view, but you should still have a solid grasp of the basics of Java multithreading for future problems. ( Proofreading note: I strongly agree with this point of view )

Java Multithreading Interview Questions

1. What is the difference between a process and a thread?

A process is a self contained runtime 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 a process and can share resources within a process.

2. What are the benefits of multithreaded 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 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 and CGI does not.

3. What is the difference between a user thread and a daemon thread?

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 prevent the JVM from terminating. When no user threads are running, the JVM closes the program and exits. A 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 a thread: one is to implement the Runnable interface, and then pass it to the Thread constructor to create a Thread object; the other is to directly inherit the Thread class. To learn more, 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 state is New. When we call the thread's start() method, 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 are Waiting, Blocked  and Dead . Read this article to learn more about the thread life cycle .

6. Can the run() method of the Thread class be called directly?

Of course, but if we call the Thread's run() method, it will behave like a normal method. To execute our code in a new thread, we must use the Thread.start() method.

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. Note that this does not terminate the thread, once the thread is woken up from sleep, the thread's state will be changed to Runnable and according to the thread schedule, it will be executed.

8. What is your understanding of thread priority?

Each thread has a priority. Generally speaking, high-priority threads will have priority at runtime, but this depends on the implementation of thread scheduling, which is OS dependent. We can define the priority of threads, but this does not guarantee that higher priority threads will execute before lower priority threads. Thread priority is an int variable (from 1-10), with 1 being the lowest priority and 10 being the highest.

9. What is Thread Scheduler and Time Slicing?

The thread scheduler is an operating system service that is responsible for allocating CPU time to threads in the Runnable state. Once we create a thread and start it, its execution depends on the implementation of the thread scheduler. Time slicing refers to the process of allocating available CPU time to available Runnable threads. Allocating CPU time can be based on thread priority or how long a thread waits. Thread scheduling is not controlled by the Java virtual machine, so it is better to let the application control it (ie don't make your program depend on thread priorities).

10. In multithreading, what is context-switching?

Context switching is the process of storing and restoring CPU state, which enables thread execution to resume execution from the point at which it was interrupted. Context switching is an essential feature of multitasking operating systems and multithreaded environments.

11. How do you ensure that the thread on which the main() method is located is the thread where the Java program ends last?

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 resources can be shared between threads, inter-thread communication is an important means of coordinating them. The wait()\notify()\notifyAll() method in the Object class can be used to communicate between threads about the lock status of a resource. Click here for more information on threads 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 become a monitor) and wait(), notify() and other methods are used to wait for the object's lock or notify other threads that the object's monitor is available. There are no locks or synchronizers available to any object in a Java thread. That's why these methods are part of the Object class, so that every class in Java has basic methods for inter-thread communication

14. Why wait(), notify() and notifyAll() must be called in synchronized methods or synchronized blocks?

When a thread needs to call the wait() method of an object, the thread must own the lock on the object, then it will release the object lock and enter the wait state until other threads call the notify() method on the object. Likewise, when a thread needs to call an object's notify() method, it releases the object's lock so that other waiting threads can acquire the object's lock. Since all of these methods require the thread to hold the object's lock, which can only be achieved through synchronization, they can only be called from synchronized methods or synchronized blocks.

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 waiting. That's why these methods are static. They can work in the currently executing thread and avoid the programmer erroneously thinking that these methods can be called from other non-running threads.

16. How to ensure thread safety?

There are many ways to ensure thread safety in Java - synchronization, using atomic concurrent classes, implementing concurrent locks, using the volatile keyword, using immutable and thread-safe classes. You can learn more in the thread safety tutorial .

17. What does the volatile keyword do in Java?

When we use the volatile keyword to modify a variable, all threads will read the variable directly and not cache it. This ensures that the variable read by the thread is consistent with the memory.

18. Synchronized method and synchronized block, which is the better choice?

A synchronized block is a better choice because it doesn't lock the entire object (of course you can make it lock the entire object). Synchronized methods lock the entire object, even if there are multiple unrelated synchronized blocks in the class, which usually causes them to stop executing and need to wait to acquire the lock on the object.

19. How to create a daemon thread?

Use the setDaemon(true) method of the Thread class to set the thread as a daemon thread. It should be noted that this method needs to be called before the start() method is called, otherwise an IllegalThreadStateException will be thrown.

20. What is ThreadLocal?

ThreadLocal is used to create thread-local variables, we know that all threads of an object will share its global variables, so these variables are not thread-safe, we can use synchronization techniques. But when we don't want to use synchronization, we can choose ThreadLocal variable.

Each thread will have their own Thread variable, and they can use the get()\set() method to get their default value or change their value within the thread. ThreadLocal instances are usually expected to be private static properties associated with thread state. You can see a small program about ThreadLocal in the ThreadLocal example article.

21. What is a Thread Group? Why is it not recommended to use it?

ThreadGroup is a class whose purpose is to provide information about thread groups.

The ThreadGroup API is weak, it doesn't offer much more functionality than Thread. It has two main functions: one is to get the list of active threads in the thread group; the other is to set the ncaught exception handler for the thread. But in Java 1.5, the Thread class also added the setUncaughtExceptionHandler(UncaughtExceptionHandler eh)  method, so ThreadGroup is outdated and it is not recommended to continue to use it.

 

22. What is a Java Thread Dump and how to get it?

A thread dump is a list of JVM active threads, which is useful for analyzing system bottlenecks and deadlocks. There are many ways to get thread dumps - using Profiler, the Kill -3 command, the jstack tool, etc. I prefer the jstack tool because it's easy to use and comes with the JDK. Since it's a terminal-based tool, we can write some scripts to periodically generate thread dumps for analysis. Read this document to learn more about generating thread dumps .

23. What is deadlock (Deadlock)? How to analyze and avoid deadlock?

Deadlock is a situation where two or more threads are blocked forever, which requires at least two or more threads and two or more resources.

To analyze the deadlock, we need to look at the thread dump of the Java application. We need to find out which threads are in state BLOCKED and what resources they are waiting for. Each resource has a unique id, and with this id we can find out which threads already own its object lock.

Avoiding nested locks, using locks only where needed and avoiding waiting indefinitely are common 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 utility class that can be used to schedule a thread to execute at a specific time in the future. The Timer class can be used to schedule 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 task and use Timer to schedule its execution.

Here is an example about java Timer .

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.

Java Concurrency Interview Questions

1. What is an atomic operation? What are the atomic classes in the Java Concurrency API?

An atomic operation is a unit of operation that is not affected by other operations. Atomic operations are necessary to avoid data inconsistency in a multithreaded environment.

int++ is not an atomic operation, so when one thread reads its value and increments it, another thread may read the previous value, which will cause an error.

To solve this problem, the increment operation must be guaranteed to be atomic, and before JDK1.5 we could use synchronization techniques to do this. As of JDK 1.5, the java.util.concurrent.atomic package provides wrapper classes for int and long types that are automatically guaranteed to be atomic for their operations and do not require synchronization. Read this article to learn about atomic classes in Java .

2. What is the Lock interface in the Java Concurrency API? What advantages does it have over synchronization?

The Lock interface provides more extensible locking operations than synchronized methods and synchronized blocks. They allow for more flexible structures, can have completely different properties, and can support conditional objects of multiple related classes.

Its advantages are:

  • Can make locks fairer
  • Allows threads to respond to interrupts while waiting for locks
  • You can let the thread try to acquire the lock and return immediately or wait for a while if the lock cannot be acquired
  • Locks can be acquired and released in different scopes and in different orders

Read more about lock examples

3. What is the Executors framework?

The Executor framework was introduced in Java 5 with the java.util.concurrent.Executor interface. The Executor framework is a framework for asynchronous tasks that are invoked, scheduled, executed and controlled according to a set of execution policies.

Unlimited creation of threads can cause application memory overflow. So creating a thread pool is a better solution because you can limit the number of threads and recycle them. Using the Executors framework can be very convenient to 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 characteristics of java.util.concurrent.BlockingQueue are: when the queue is empty, the operation of getting or removing elements from the queue will be blocked, or when the queue is full, the operation of adding elements to the queue will be blocked.

Blocking queues don't accept null values, it throws NullPointerException when you try to add a null value to the queue.

Implementations of blocking queues are thread-safe, all query methods are atomic and use internal locks or other forms of concurrency control.

The BlockingQueue interface is part of the java collections framework and is mainly used to implement the producer-consumer problem.

Read this article to learn how to implement the producer-consumer problem using blocking queues.

5. What are Callable and Future?

Java 5 introduced the java.util.concurrent.Callable interface in the concurrency package, which is 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 the Callable in the 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 the get() method so that we can wait for the Callable to end and get its execution result.

Read this article for more examples of Callable, Future .

6. What is FutureTask?

FutureTask is a basic implementation of Future, we can use it with Executors to process asynchronous tasks. Usually we don't need to use the FutureTask class, it becomes very useful only when we intend to override some methods of the Future interface and keep the original basic implementation. We can just inherit from it and override the methods we need. Read the Java FutureTask example to learn how to use it.

7. What is the implementation of concurrent containers?

Java collection classes are fail-fast, which means that the iterator's next() method will throw a ConcurrentModificationException when the collection is mutated and a thread is traversing the collection using the iterator.

Concurrent containers support concurrent traversals 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 provide some utility methods for the Executor, ExecutorService, ScheduledExecutorService, ThreadFactory and Callable classes.

Executors can be used to easily create thread pools

 

9. Why is ConcurrentHashMap weakly consistent? And why won't ConcurrentModificationException be reported when multiple threads modify ConcurrentHashMap concurrently?

  Reference: http://ifeve.com/java-concurrent-hashmap-2/

       http://ifeve.com/concurrenthashmap-weakly-consistent/

     http://blog.csdn.net/liuzhengkang/article/details/2916620

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325120618&siteId=291194637