An ExecutorService that executes each submitted task using one of possibly several pooled threads, normally configured using Executors factory methods.

Thread pools address two different problems: they usually provide improved performance when executing large numbers of asynchronous tasks, due to reduced per-task invocation overhead, and they provide a means of bounding and managing the resources, including threads, consumed when executing a collection of tasks. Each ThreadPoolExecutor also maintains some basic statistics, such as the number of completed tasks.

To be useful across a wide range of contexts, this class provides many adjustable parameters and extensibility hooks. However, programmers are urged to use the more convenient Executors factory methods Executors#newCachedThreadPool (unbounded thread pool, with automatic thread reclamation), Executors#newFixedThreadPool (fixed size thread pool) and Executors#newSingleThreadExecutor (single background thread), that preconfigure settings for the most common usage scenarios. Otherwise, use the following guide when manually configuring and tuning this class:

Core and maximum pool sizes
A ThreadPoolExecutor will automatically adjust the pool size (see ThreadPoolExecutor#getPoolSize ) according to the bounds set by corePoolSize (see ThreadPoolExecutor#getCorePoolSize ) and maximumPoolSize (see ThreadPoolExecutor#getMaximumPoolSize ). When a new task is submitted in method ThreadPoolExecutor#execute , and fewer than corePoolSize threads are running, a new thread is created to handle the request, even if other worker threads are idle. If there are more than corePoolSize but less than maximumPoolSize threads running, a new thread will be created only if the queue is full. By setting corePoolSize and maximumPoolSize the same, you create a fixed-size thread pool. By setting maximumPoolSize to an essentially unbounded value such as Integer.MAX_VALUE, you allow the pool to accommodate an arbitrary number of concurrent tasks. Most typically, core and maximum pool sizes are set only upon construction, but they may also be changed dynamically using ThreadPoolExecutor#setCorePoolSize and ThreadPoolExecutor#setMaximumPoolSize .
On-demand construction
By default, even core threads are initially created and started only when needed by new tasks, but this can be overridden dynamically using method ThreadPoolExecutor#prestartCoreThread or ThreadPoolExecutor#prestartAllCoreThreads .
Creating new threads
New threads are created using a java.util.concurrent.ThreadFactory . If not otherwise specified, a Executors#defaultThreadFactory is used, that creates threads to all be in the same ThreadGroup and with the same NORM_PRIORITY priority and non-daemon status. By supplying a different ThreadFactory, you can alter the thread's name, thread group, priority, daemon status, etc. If a ThreadFactory fails to create a thread when asked by returning null from newThread, the executor will continue, but might not be able to execute any tasks.
Keep-alive times
If the pool currently has more than corePoolSize threads, excess threads will be terminated if they have been idle for more than the keepAliveTime (see ThreadPoolExecutor#getKeepAliveTime ). This provides a means of reducing resource consumption when the pool is not being actively used. If the pool becomes more active later, new threads will be constructed. This parameter can also be changed dynamically using method ThreadPoolExecutor#setKeepAliveTime . Using a value of Long.MAX_VALUE TimeUnit#NANOSECONDS effectively disables idle threads from ever terminating prior to shut down.
Queuing
Any BlockingQueue may be used to transfer and hold submitted tasks. The use of this queue interacts with pool sizing:
  • If fewer than corePoolSize threads are running, the Executor always prefers adding a new thread rather than queuing.
  • If corePoolSize or more threads are running, the Executor always prefers queuing a request rather than adding a new thread.
  • If a request cannot be queued, a new thread is created unless this would exceed maximumPoolSize, in which case, the task will be rejected.
There are three general strategies for queuing:
  1. Direct handoffs. A good default choice for a work queue is a SynchronousQueue that hands off tasks to threads without otherwise holding them. Here, an attempt to queue a task will fail if no threads are immediately available to run it, so a new thread will be constructed. This policy avoids lockups when handling sets of requests that might have internal dependencies. Direct handoffs generally require unbounded maximumPoolSizes to avoid rejection of new submitted tasks. This in turn admits the possibility of unbounded thread growth when commands continue to arrive on average faster than they can be processed.
  2. Unbounded queues. Using an unbounded queue (for example a LinkedBlockingQueue without a predefined capacity) will cause new tasks to be queued in cases where all corePoolSize threads are busy. Thus, no more than corePoolSize threads will ever be created. (And the value of the maximumPoolSize therefore doesn't have any effect.) This may be appropriate when each task is completely independent of others, so tasks cannot affect each others execution; for example, in a web page server. While this style of queuing can be useful in smoothing out transient bursts of requests, it admits the possibility of unbounded work queue growth when commands continue to arrive on average faster than they can be processed.
  3. Bounded queues. A bounded queue (for example, an ArrayBlockingQueue ) helps prevent resource exhaustion when used with finite maximumPoolSizes, but can be more difficult to tune and control. Queue sizes and maximum pool sizes may be traded off for each other: Using large queues and small pools minimizes CPU usage, OS resources, and context-switching overhead, but can lead to artificially low throughput. If tasks frequently block (for example if they are I/O bound), a system may be able to schedule time for more threads than you otherwise allow. Use of small queues generally requires larger pool sizes, which keeps CPUs busier but may encounter unacceptable scheduling overhead, which also decreases throughput.
Rejected tasks
New tasks submitted in method ThreadPoolExecutor#execute will be rejected when the Executor has been shut down, and also when the Executor uses finite bounds for both maximum threads and work queue capacity, and is saturated. In either case, the execute method invokes the RejectedExecutionHandler#rejectedExecution method of its RejectedExecutionHandler . Four predefined handler policies are provided:
  1. In the default ThreadPoolExecutor.AbortPolicy , the handler throws a runtime RejectedExecutionException upon rejection.
  2. In ThreadPoolExecutor.CallerRunsPolicy , the thread that invokes execute itself runs the task. This provides a simple feedback control mechanism that will slow down the rate that new tasks are submitted.
  3. In ThreadPoolExecutor.DiscardPolicy , a task that cannot be executed is simply dropped.
  4. In ThreadPoolExecutor.DiscardOldestPolicy , if the executor is not shut down, the task at the head of the work queue is dropped, and then execution is retried (which can fail again, causing this to be repeated.)
It is possible to define and use other kinds of RejectedExecutionHandler classes. Doing so requires some care especially when policies are designed to work only under particular capacity or queuing policies.
Hook methods
This class provides protected overridable ThreadPoolExecutor#beforeExecute and ThreadPoolExecutor#afterExecute methods that are called before and after execution of each task. These can be used to manipulate the execution environment; for example, reinitializing ThreadLocals, gathering statistics, or adding log entries. Additionally, method ThreadPoolExecutor#terminated can be overridden to perform any special processing that needs to be done once the Executor has fully terminated.

If hook or callback methods throw exceptions, internal worker threads may in turn fail and abruptly terminate.

Queue maintenance
Method ThreadPoolExecutor#getQueue allows access to the work queue for purposes of monitoring and debugging. Use of this method for any other purpose is strongly discouraged. Two supplied methods, ThreadPoolExecutor#remove and ThreadPoolExecutor#purge are available to assist in storage reclamation when large numbers of queued tasks become cancelled.

Extension example. Most extensions of this class override one or more of the protected hook methods. For example, here is a subclass that adds a simple pause/resume feature:

 class PausableThreadPoolExecutor extends ThreadPoolExecutor {
   private boolean isPaused;
   private ReentrantLock pauseLock = new ReentrantLock();
   private Condition unpaused = pauseLock.newCondition();

   public PausableThreadPoolExecutor(...) { super(...); }
 
   protected void beforeExecute(Thread t, Runnable r) {
     super.beforeExecute(t, r);
     pauseLock.lock();
     try {
       while (isPaused) unpaused.await();
     } catch(InterruptedException ie) {
       t.interrupt();
     } finally {
       pauseLock.unlock();
     }
   }
 
   public void pause() {
     pauseLock.lock();
     try {
       isPaused = true;
     } finally {
       pauseLock.unlock();
     }
   }
 
   public void resume() {
     pauseLock.lock();
     try {
       isPaused = false;
       unpaused.signalAll();
     } finally {
       pauseLock.unlock();
     }
   }
 }
 
@since
1.5
@author
Doug Lea
Creates a new ThreadPoolExecutor with the given initial parameters and default thread factory and handler. It may be more convenient to use one of the Executors factory methods instead of this general purpose constructor.
Parameters
corePoolSizethe number of threads to keep in the pool, even if they are idle.
maximumPoolSizethe maximum number of threads to allow in the pool.
keepAliveTimewhen the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating.
unitthe time unit for the keepAliveTime argument.
workQueuethe queue to use for holding tasks before they are executed. This queue will hold only the Runnable tasks submitted by the execute method.
Throws
IllegalArgumentExceptionif corePoolSize, or keepAliveTime less than zero, or if maximumPoolSize less than or equal to zero, or if corePoolSize greater than maximumPoolSize.
NullPointerExceptionif workQueue is null
Creates a new ThreadPoolExecutor with the given initial parameters.
Parameters
corePoolSizethe number of threads to keep in the pool, even if they are idle.
maximumPoolSizethe maximum number of threads to allow in the pool.
keepAliveTimewhen the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating.
unitthe time unit for the keepAliveTime argument.
workQueuethe queue to use for holding tasks before they are executed. This queue will hold only the Runnable tasks submitted by the execute method.
threadFactorythe factory to use when the executor creates a new thread.
Throws
IllegalArgumentExceptionif corePoolSize, or keepAliveTime less than zero, or if maximumPoolSize less than or equal to zero, or if corePoolSize greater than maximumPoolSize.
NullPointerExceptionif workQueue or threadFactory are null.
Creates a new ThreadPoolExecutor with the given initial parameters.
Parameters
corePoolSizethe number of threads to keep in the pool, even if they are idle.
maximumPoolSizethe maximum number of threads to allow in the pool.
keepAliveTimewhen the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating.
unitthe time unit for the keepAliveTime argument.
workQueuethe queue to use for holding tasks before they are executed. This queue will hold only the Runnable tasks submitted by the execute method.
handlerthe handler to use when execution is blocked because the thread bounds and queue capacities are reached.
Throws
IllegalArgumentExceptionif corePoolSize, or keepAliveTime less than zero, or if maximumPoolSize less than or equal to zero, or if corePoolSize greater than maximumPoolSize.
NullPointerExceptionif workQueue or handler are null.
Creates a new ThreadPoolExecutor with the given initial parameters.
Parameters
corePoolSizethe number of threads to keep in the pool, even if they are idle.
maximumPoolSizethe maximum number of threads to allow in the pool.
keepAliveTimewhen the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating.
unitthe time unit for the keepAliveTime argument.
workQueuethe queue to use for holding tasks before they are executed. This queue will hold only the Runnable tasks submitted by the execute method.
threadFactorythe factory to use when the executor creates a new thread.
handlerthe handler to use when execution is blocked because the thread bounds and queue capacities are reached.
Throws
IllegalArgumentExceptionif corePoolSize, or keepAliveTime less than zero, or if maximumPoolSize less than or equal to zero, or if corePoolSize greater than maximumPoolSize.
NullPointerExceptionif workQueue or threadFactory or handler are null.
Indicates whether some other object is "equal to" this one.

The equals method implements an equivalence relation on non-null object references:

  • It is reflexive: for any non-null reference value x, x.equals(x) should return true.
  • It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
  • For any non-null reference value x, x.equals(null) should return false.

The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).

Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.

Parameters
objthe reference object with which to compare.
Return
true if this object is the same as the obj argument; false otherwise.
Executes the given task sometime in the future. The task may execute in a new thread or in an existing pooled thread. If the task cannot be submitted for execution, either because this executor has been shutdown or because its capacity has been reached, the task is handled by the current RejectedExecutionHandler.
Parameters
commandthe task to execute
Throws
RejectedExecutionExceptionat discretion of RejectedExecutionHandler, if task cannot be accepted for execution
NullPointerExceptionif command is null
Returns the approximate number of threads that are actively executing tasks.
Return
the number of threads
Returns the runtime class of an object. That Class object is the object that is locked by static synchronized methods of the represented class.
Return
The java.lang.Class object that represents the runtime class of the object. The result is of type {@code Class} where X is the erasure of the static type of the expression on which getClass is called.
Returns the approximate total number of tasks that have completed execution. Because the states of tasks and threads may change dynamically during computation, the returned value is only an approximation, but one that does not ever decrease across successive calls.
Return
the number of tasks
Returns the core number of threads.
Return
the core number of threads
Returns the thread keep-alive time, which is the amount of time which threads in excess of the core pool size may remain idle before being terminated.
Parameters
unitthe desired time unit of the result
Return
the time limit
Returns the largest number of threads that have ever simultaneously been in the pool.
Return
the number of threads
Returns the maximum allowed number of threads.
Return
the maximum allowed number of threads
Returns the current number of threads in the pool.
Return
the number of threads
Returns the task queue used by this executor. Access to the task queue is intended primarily for debugging and monitoring. This queue may be in active use. Retrieving the task queue does not prevent queued tasks from executing.
Return
the task queue
Returns the current handler for unexecutable tasks.
Return
the current handler
Returns the approximate total number of tasks that have been scheduled for execution. Because the states of tasks and threads may change dynamically during computation, the returned value is only an approximation, but one that does not ever decrease across successive calls.
Return
the number of tasks
Returns the thread factory used to create new threads.
Return
the current thread factory
Returns a hash code value for the object. This method is supported for the benefit of hashtables such as those provided by java.util.Hashtable.

The general contract of hashCode is:

  • Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
  • If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
  • It is not required that if two objects are unequal according to the method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.

As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)

Return
a hash code value for this object.
Returns true if this executor is in the process of terminating after shutdown or shutdownNow but has not completely terminated. This method may be useful for debugging. A return of true reported a sufficient period after shutdown may indicate that submitted tasks have ignored or suppressed interruption, causing this executor not to properly terminate.
Return
true if terminating but not yet terminated.
Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation. A thread waits on an object's monitor by calling one of the wait methods.

The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object. The awakened thread will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object.

This method should only be called by a thread that is the owner of this object's monitor. A thread becomes the owner of the object's monitor in one of three ways:

  • By executing a synchronized instance method of that object.
  • By executing the body of a synchronized statement that synchronizes on the object.
  • For objects of type Class, by executing a synchronized static method of that class.

Only one thread at a time can own an object's monitor.

Throws
IllegalMonitorStateExceptionif the current thread is not the owner of this object's monitor.
Wakes up all threads that are waiting on this object's monitor. A thread waits on an object's monitor by calling one of the wait methods.

The awakened threads will not be able to proceed until the current thread relinquishes the lock on this object. The awakened threads will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened threads enjoy no reliable privilege or disadvantage in being the next thread to lock this object.

This method should only be called by a thread that is the owner of this object's monitor. See the notify method for a description of the ways in which a thread can become the owner of a monitor.

Throws
IllegalMonitorStateExceptionif the current thread is not the owner of this object's monitor.
Starts all core threads, causing them to idly wait for work. This overrides the default policy of starting core threads only when new tasks are executed.
Return
the number of threads started.
Starts a core thread, causing it to idly wait for work. This overrides the default policy of starting core threads only when new tasks are executed. This method will return false if all core threads have already been started.
Return
true if a thread was started
Tries to remove from the work queue all Future tasks that have been cancelled. This method can be useful as a storage reclamation operation, that has no other impact on functionality. Cancelled tasks are never executed, but may accumulate in work queues until worker threads can actively remove them. Invoking this method instead tries to remove them now. However, this method may fail to remove tasks in the presence of interference by other threads.
Removes this task from the executor's internal queue if it is present, thus causing it not to be run if it has not already started.

This method may be useful as one part of a cancellation scheme. It may fail to remove tasks that have been converted into other forms before being placed on the internal queue. For example, a task entered using submit might be converted into a form that maintains Future status. However, in such cases, method ThreadPoolExecutor#purge may be used to remove those Futures that have been cancelled.

Parameters
taskthe task to remove
Return
true if the task was removed
Sets the core number of threads. This overrides any value set in the constructor. If the new value is smaller than the current value, excess existing threads will be terminated when they next become idle. If larger, new threads will, if needed, be started to execute any queued tasks.
Parameters
corePoolSizethe new core size
Throws
IllegalArgumentExceptionif corePoolSize less than zero
Sets the time limit for which threads may remain idle before being terminated. If there are more than the core number of threads currently in the pool, after waiting this amount of time without processing a task, excess threads will be terminated. This overrides any value set in the constructor.
Parameters
timethe time to wait. A time value of zero will cause excess threads to terminate immediately after executing tasks.
unitthe time unit of the time argument
Throws
IllegalArgumentExceptionif time less than zero
Sets the maximum allowed number of threads. This overrides any value set in the constructor. If the new value is smaller than the current value, excess existing threads will be terminated when they next become idle.
Parameters
maximumPoolSizethe new maximum
Throws
IllegalArgumentExceptionif maximumPoolSize less than zero or the {@link #getCorePoolSize core pool size}
Sets a new handler for unexecutable tasks.
Parameters
handlerthe new handler
Throws
NullPointerExceptionif handler is null
Sets the thread factory used to create new threads.
Parameters
threadFactorythe new thread factory
Throws
NullPointerExceptionif threadFactory is null
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.
Throws
SecurityExceptionif a security manager exists and shutting down this ExecutorService may manipulate threads that the caller is not permitted to modify because it does not hold {@link java.lang.RuntimePermission}("modifyThread"), or the security manager's checkAccess method denies access.
Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution.

This implementation cancels tasks via Thread#interrupt , so if any tasks mask or fail to respond to interrupts, they may never terminate.

Return
list of tasks that never commenced execution
Throws
SecurityExceptionif a security manager exists and shutting down this ExecutorService may manipulate threads that the caller is not permitted to modify because it does not hold {@link java.lang.RuntimePermission}("modifyThread"), or the security manager's checkAccess method denies access.
Returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read. It is recommended that all subclasses override this method.

The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:

 getClass().getName() + '@' + Integer.toHexString(hashCode())
 
Return
a string representation of the object.
Causes current thread to wait until another thread invokes the method or the method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0).

The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.

As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:

     synchronized (obj) {
         while (<condition does not hold>)
             obj.wait();
         ... // Perform action appropriate to condition
     }
 
This method should only be called by a thread that is the owner of this object's monitor. See the notify method for a description of the ways in which a thread can become the owner of a monitor.
Throws
IllegalMonitorStateExceptionif the current thread is not the owner of the object's monitor.
InterruptedExceptionif another thread interrupted the current thread before or while the current thread was waiting for a notification. The interrupted status of the current thread is cleared when this exception is thrown.
Causes current thread to wait until either another thread invokes the method or the method for this object, or a specified amount of time has elapsed.

The current thread must own this object's monitor.

This method causes the current thread (call it T) to place itself in the wait set for this object and then to relinquish any and all synchronization claims on this object. Thread T becomes disabled for thread scheduling purposes and lies dormant until one of four things happens:

  • Some other thread invokes the notify method for this object and thread T happens to be arbitrarily chosen as the thread to be awakened.
  • Some other thread invokes the notifyAll method for this object.
  • Some other thread interrupts thread T.
  • The specified amount of real time has elapsed, more or less. If timeout is zero, however, then real time is not taken into consideration and the thread simply waits until notified.
The thread T is then removed from the wait set for this object and re-enabled for thread scheduling. It then competes in the usual manner with other threads for the right to synchronize on the object; once it has gained control of the object, all its synchronization claims on the object are restored to the status quo ante - that is, to the situation as of the time that the wait method was invoked. Thread T then returns from the invocation of the wait method. Thus, on return from the wait method, the synchronization state of the object and of thread T is exactly as it was when the wait method was invoked.

A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup. While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied. In other words, waits should always occur in loops, like this one:

     synchronized (obj) {
         while (<condition does not hold>)
             obj.wait(timeout);
         ... // Perform action appropriate to condition
     }
 
(For more information on this topic, see Section 3.2.3 in Doug Lea's "Concurrent Programming in Java (Second Edition)" (Addison-Wesley, 2000), or Item 50 in Joshua Bloch's "Effective Java Programming Language Guide" (Addison-Wesley, 2001).

If the current thread is interrupted by another thread while it is waiting, then an InterruptedException is thrown. This exception is not thrown until the lock status of this object has been restored as described above.

Note that the wait method, as it places the current thread into the wait set for this object, unlocks only this object; any other objects on which the current thread may be synchronized remain locked while the thread waits.

This method should only be called by a thread that is the owner of this object's monitor. See the notify method for a description of the ways in which a thread can become the owner of a monitor.

Parameters
timeoutthe maximum time to wait in milliseconds.
Throws
IllegalArgumentExceptionif the value of timeout is negative.
IllegalMonitorStateExceptionif the current thread is not the owner of the object's monitor.
InterruptedExceptionif another thread interrupted the current thread before or while the current thread was waiting for a notification. The interrupted status of the current thread is cleared when this exception is thrown.
Causes current thread to wait until another thread invokes the method or the method for this object, or some other thread interrupts the current thread, or a certain amount of real time has elapsed.

This method is similar to the wait method of one argument, but it allows finer control over the amount of time to wait for a notification before giving up. The amount of real time, measured in nanoseconds, is given by:

 1000000*timeout+nanos

In all other respects, this method does the same thing as the method of one argument. In particular, wait(0, 0) means the same thing as wait(0).

The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until either of the following two conditions has occurred:

  • Another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method.
  • The timeout period, specified by timeout milliseconds plus nanos nanoseconds arguments, has elapsed.

The thread then waits until it can re-obtain ownership of the monitor and resumes execution.

As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:

     synchronized (obj) {
         while (<condition does not hold>)
             obj.wait(timeout, nanos);
         ... // Perform action appropriate to condition
     }
 
This method should only be called by a thread that is the owner of this object's monitor. See the notify method for a description of the ways in which a thread can become the owner of a monitor.
Parameters
timeoutthe maximum time to wait in milliseconds.
nanosadditional time, in nanoseconds range 0-999999.
Throws
IllegalArgumentExceptionif the value of timeout is negative or the value of nanos is not in the range 0-999999.
IllegalMonitorStateExceptionif the current thread is not the owner of this object's monitor.
InterruptedExceptionif another thread interrupted the current thread before or while the current thread was waiting for a notification. The interrupted status of the current thread is cleared when this exception is thrown.