public synchronized T get ( final int timeoutMillis ) throws E { if ( mReal != null ) { return mReal ; } if ( mBogus != null && mMinRetryDelayMillis < 0 ) { return mBogus ; } if ( mCreateThread == null ) { mCreateThread = new CreateThread ( ) ; cThreadPool . submit ( mCreateThread ) ; } if ( timeoutMillis != 0 ) { final long start = System . nanoTime ( ) ; try { if ( timeoutMillis < 0 ) { while ( mReal == null && mCreateThread != null ) { if ( timeoutMillis < 0 ) { wait ( ) ; } } } else { long remaining = timeoutMillis ; while ( mReal == null && mCreateThread != null && ! mFailed ) { wait ( remaining ) ; long elapsed = ( System . nanoTime ( ) - start ) / 1000000L ; if ( ( remaining -= elapsed ) <= 0 ) { break ; } } } } catch ( InterruptedException e ) { } if ( mReal != null ) { return mReal ; } long elapsed = ( System . nanoTime ( ) - start ) / 1000000L ; if ( elapsed >= timeoutMillis ) { timedOutNotification ( elapsed ) ; } } if ( mFailedError != null ) { // Take ownership of error. Also stitch traces together for // context. This gives the illusion that the creation attempt // occurred in this thread. Throwable error = mFailedError ; mFailedError = null ; StackTraceElement [ ] trace = error . getStackTrace ( ) ; error . fillInStackTrace ( ) ; StackTraceElement [ ] localTrace = error . getStackTrace ( ) ; StackTraceElement [ ] completeTrace = new StackTraceElement [ trace . length + localTrace . length ] ; System . arraycopy ( trace , 0 , completeTrace , 0 , trace . length ) ; System . arraycopy ( localTrace , 0 , completeTrace , trace . length , localTrace . length ) ; error . setStackTrace ( completeTrace ) ; ThrowUnchecked . fire ( error ) ; } if ( mBogus == null ) { mRef = new AtomicReference < T > ( createBogus ( ) ) ; mBogus = AccessController . doPrivileged ( new PrivilegedAction < T > ( ) { public T run ( ) { try { return getWrapper ( ) . newInstance ( mRef ) ; } catch ( Exception e ) { ThrowUnchecked . fire ( e ) ; return null ; } } } ) ; } return mBogus ; }
Returns real or bogus object . If real object is returned then future invocations of this method return the same real object instance . This method waits for the real object to be created if it is blocked . If real object creation fails immediately then this method will not wait returning a bogus object immediately instead .