Constructors Summary |
---|
public Thread()Constructs a new {@code Thread} with no {@code Runnable} object and a
newly generated name. The new {@code Thread} will belong to the same
{@code ThreadGroup} as the {@code Thread} calling this constructor.
create(null, null, null, 0);
|
public Thread(Runnable runnable)Constructs a new {@code Thread} with a {@code Runnable} object and a
newly generated name. The new {@code Thread} will belong to the same
{@code ThreadGroup} as the {@code Thread} calling this constructor.
create(null, runnable, null, 0);
|
public Thread(Runnable runnable, String threadName)Constructs a new {@code Thread} with a {@code Runnable} object and name
provided. The new {@code Thread} will belong to the same {@code
ThreadGroup} as the {@code Thread} calling this constructor.
if (threadName == null) {
throw new NullPointerException();
}
create(null, runnable, threadName, 0);
|
public Thread(String threadName)Constructs a new {@code Thread} with no {@code Runnable} object and the
name provided. The new {@code Thread} will belong to the same {@code
ThreadGroup} as the {@code Thread} calling this constructor.
if (threadName == null) {
throw new NullPointerException();
}
create(null, null, threadName, 0);
|
public Thread(ThreadGroup group, Runnable runnable)Constructs a new {@code Thread} with a {@code Runnable} object and a
newly generated name. The new {@code Thread} will belong to the {@code
ThreadGroup} passed as parameter.
create(group, runnable, null, 0);
|
public Thread(ThreadGroup group, Runnable runnable, String threadName)Constructs a new {@code Thread} with a {@code Runnable} object, the given
name and belonging to the {@code ThreadGroup} passed as parameter.
if (threadName == null) {
throw new NullPointerException();
}
create(group, runnable, threadName, 0);
|
public Thread(ThreadGroup group, String threadName)Constructs a new {@code Thread} with no {@code Runnable} object, the
given name and belonging to the {@code ThreadGroup} passed as parameter.
if (threadName == null) {
throw new NullPointerException();
}
create(group, null, threadName, 0);
|
public Thread(ThreadGroup group, Runnable runnable, String threadName, long stackSize)Constructs a new {@code Thread} with a {@code Runnable} object, the given
name and belonging to the {@code ThreadGroup} passed as parameter.
if (threadName == null) {
throw new NullPointerException();
}
create(group, runnable, threadName, stackSize);
|
Thread(ThreadGroup group, String name, int priority, boolean daemon)Package-scope method invoked by Dalvik VM to create "internal"
threads or attach threads created externally.
Don't call Thread.currentThread(), since there may not be such
a thing (e.g. for Main).
synchronized (Thread.class) {
id = ++Thread.count;
}
if (name == null) {
this.name = "Thread-" + id;
} else
this.name = name;
if (group == null) {
throw new InternalError("group not specified");
}
this.group = group;
this.target = null;
this.stackSize = 0;
this.priority = priority;
this.daemon = daemon;
/* add ourselves to our ThreadGroup of choice */
this.group.addThread(this);
|
Methods Summary |
---|
public static int | activeCount()Returns the number of active {@code Thread}s in the running {@code
Thread}'s group and its subgroups.
return currentThread().getThreadGroup().activeCount();
|
public final void | checkAccess()Is used for operations that require approval from a SecurityManager. If
there's none installed, this method is a no-op. If there's a
SecurityManager installed, {@link SecurityManager#checkAccess(Thread)} is
called for that SecurityManager.
// Forwards the message to the SecurityManager (if there's one) passing
// the receiver as parameter
SecurityManager currentManager = System.getSecurityManager();
if (currentManager != null) {
currentManager.checkAccess(this);
}
|
public int | countStackFrames()Returns the number of stack frames in this thread.
return getStackTrace().length;
|
private void | create(java.lang.ThreadGroup group, java.lang.Runnable runnable, java.lang.String threadName, long stackSize)Initializes a new, existing Thread object with a runnable object,
the given name and belonging to the ThreadGroup passed as parameter.
This is the method that the several public constructors delegate their
work to.
SecurityManager smgr = System.getSecurityManager();
if (smgr != null) {
if (group == null) {
group = smgr.getThreadGroup();
}
/*
* Freaky security requirement: If the Thread's class is actually
* a subclass of Thread and it tries to override either
* getContextClassLoader() or setContextClassLoader(), the
* SecurityManager has to allow this.
*/
if (getClass() != Thread.class) {
Class[] signature = new Class[] { ClassLoader.class };
try {
getClass().getDeclaredMethod("getContextClassLoader", signature);
smgr.checkPermission(new RuntimePermission("enableContextClassLoaderOverride"));
} catch (NoSuchMethodException ex) {
// Ignore. Just interested in the method's existence.
}
try {
getClass().getDeclaredMethod("setContextClassLoader", signature);
smgr.checkPermission(new RuntimePermission("enableContextClassLoaderOverride"));
} catch (NoSuchMethodException ex) {
// Ignore. Just interested in the method's existence.
}
}
}
Thread currentThread = Thread.currentThread();
if (group == null) {
group = currentThread.getThreadGroup();
}
group.checkAccess();
if (group.isDestroyed()) {
throw new IllegalThreadStateException("Group already destroyed");
}
this.group = group;
synchronized (Thread.class) {
id = ++Thread.count;
}
if (threadName == null) {
this.name = "Thread-" + id;
} else {
this.name = threadName;
}
this.target = runnable;
this.stackSize = stackSize;
this.priority = currentThread.getPriority();
// Transfer over InheritableThreadLocals.
if (currentThread.inheritableValues != null) {
inheritableValues
= new ThreadLocal.Values(currentThread.inheritableValues);
}
// store current AccessControlContext as inherited context for this thread
SecurityUtils.putContext(this, AccessController.getContext());
// add ourselves to our ThreadGroup of choice
this.group.addThread(this);
|
public static java.lang.Thread | currentThread()Returns the Thread of the caller, that is, the current Thread.
return VMThread.currentThread();
|
public void | destroy()Destroys the receiver without any monitor cleanup.
throw new NoSuchMethodError("Thread.destroy()"); // TODO Externalize???
|
public static void | dumpStack()Prints to the standard error stream a text representation of the current
stack for this Thread.
new Throwable("stack dump").printStackTrace();
|
public static int | enumerate(java.lang.Thread[] threads)Copies an array with all Threads which are in the same ThreadGroup as the
receiver - and subgroups - into the array threads passed as
parameter. If the array passed as parameter is too small no exception is
thrown - the extra elements are simply not copied.
Thread thread = Thread.currentThread();
thread.checkAccess();
return thread.getThreadGroup().enumerate(threads);
|
public static java.util.Map | getAllStackTraces()
Returns the stack traces of all the currently live threads and puts them
into the given map.
SecurityManager securityManager = System.getSecurityManager();
if (securityManager != null) {
securityManager.checkPermission(new RuntimePermission("getStackTrace"));
securityManager.checkPermission(new RuntimePermission("modifyThreadGroup"));
}
Map<Thread, StackTraceElement[]> map = new HashMap<Thread, StackTraceElement[]>();
// Find out how many live threads we have. Allocate a bit more
// space than needed, in case new ones are just being created.
int count = ThreadGroup.mSystem.activeCount();
Thread[] threads = new Thread[count + count / 2];
// Enumerate the threads and collect the stacktraces.
count = ThreadGroup.mSystem.enumerate(threads);
for (int i = 0; i < count; i++) {
map.put(threads[i], threads[i].getStackTrace());
}
return map;
|
public java.lang.ClassLoader | getContextClassLoader()Returns the context ClassLoader for this Thread.
If the conditions
- there is a security manager
- the caller's class loader is not null
- the caller's class loader is not the same as the requested
context class loader and not an ancestor thereof
are satisfied, a security check for
RuntimePermission("getClassLoader") is performed first.
// First, if the conditions
// 1) there is a security manager
// 2) the caller's class loader is not null
// 3) the caller's class loader is not the same as the context
// class loader and not an ancestor thereof
// are satisfied we should perform a security check.
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader calling = VMStack.getCallingClassLoader();
if (calling != null && !calling.isAncestorOf(contextClassLoader)) {
sm.checkPermission(new RuntimePermission("getClassLoader"));
}
}
return contextClassLoader;
|
public static java.lang.Thread$UncaughtExceptionHandler | getDefaultUncaughtExceptionHandler()Returns the default exception handler that's executed when uncaught
exception terminates a thread.
return defaultUncaughtHandler;
|
public long | getId()Returns the thread's identifier. The ID is a positive long
generated on thread creation, is unique to the thread, and doesn't change
during the lifetime of the thread; the ID may be reused after the thread
has been terminated.
return id;
|
public final java.lang.String | getName()Returns the name of the Thread.
return name;
|
public final int | getPriority()Returns the priority of the Thread.
return priority;
|
public java.lang.StackTraceElement[] | getStackTrace()Returns the a stack trace representing the current execution state of
this Thread.
The RuntimePermission("getStackTrace") is checked before
returning a result.
SecurityManager securityManager = System.getSecurityManager();
if (securityManager != null) {
securityManager.checkPermission(new RuntimePermission("getStackTrace"));
}
StackTraceElement ste[] = VMStack.getThreadStackTrace(this);
return ste != null ? ste : new StackTraceElement[0];
|
public java.lang.Thread$State | getState()Returns the current state of the Thread. This method is useful for
monitoring purposes.
// TODO This is ugly and should be implemented better.
VMThread vmt = this.vmThread;
// Make sure we have a valid reference to an object. If native code
// deletes the reference we won't run into a null reference later.
VMThread thread = vmThread;
if (thread != null) {
// If the Thread Object became invalid or was not yet started,
// getStatus() will return -1.
int state = thread.getStatus();
if(state != -1) {
return VMThread.STATE_MAP[state];
}
}
return hasBeenStarted ? Thread.State.TERMINATED : Thread.State.NEW;
|
public final java.lang.ThreadGroup | getThreadGroup()Returns the ThreadGroup to which this Thread belongs.
// TODO This should actually be done at native termination.
if (getState() == Thread.State.TERMINATED) {
return null;
} else {
return group;
}
|
public java.lang.Thread$UncaughtExceptionHandler | getUncaughtExceptionHandler()Returns the thread's uncaught exception handler. If not explicitly set,
then the ThreadGroup's handler is returned. If the thread is terminated,
then null is returned.
if (uncaughtHandler != null)
return uncaughtHandler;
else
return group; // ThreadGroup is instance of UEH
|
public static boolean | holdsLock(java.lang.Object object)Indicates whether the current Thread has a monitor lock on the specified
object.
return currentThread().vmThread.holdsLock(object);
|
public void | interrupt()Posts an interrupt request to this {@code Thread}. Unless the caller is
the {@link #currentThread()}, the method {@code checkAccess()} is called
for the installed {@code SecurityManager}, if any. This may result in a
{@code SecurityException} being thrown. The further behavior depends on
the state of this {@code Thread}:
-
{@code Thread}s blocked in one of {@code Object}'s {@code wait()} methods
or one of {@code Thread}'s {@code join()} or {@code sleep()} methods will
be woken up, their interrupt status will be cleared, and they receive an
{@link InterruptedException}.
-
{@code Thread}s blocked in an I/O operation of an
{@link java.nio.channels.InterruptibleChannel} will have their interrupt
status set and receive an
{@link java.nio.channels.ClosedByInterruptException}. Also, the channel
will be closed.
-
{@code Thread}s blocked in a {@link java.nio.channels.Selector} will have
their interrupt status set and return immediately. They don't receive an
exception in this case.
checkAccess();
if (interruptAction != null) {
interruptAction.run();
}
VMThread vmt = this.vmThread;
if (vmt != null) {
vmt.interrupt();
}
|
public static boolean | interrupted()Returns a boolean indicating whether the current Thread (
currentThread() ) has a pending interrupt request (
true ) or not (false ). It also has the side-effect of
clearing the flag.
return VMThread.interrupted();
|
public final boolean | isAlive()Returns true if the receiver has already been started and
still runs code (hasn't died yet). Returns false either if
the receiver hasn't been started yet or if it has already started and run
to completion and died.
Thread.State state = getState();
return (state != Thread.State.TERMINATED && state != Thread.State.NEW);
|
public final boolean | isDaemon()Returns a boolean indicating whether the receiver is a
daemon Thread (true ) or not (false ) A
daemon Thread only runs as long as there are non-daemon Threads running.
When the last non-daemon Thread ends, the whole program ends no matter if
it had daemon Threads still running or not.
return daemon;
|
public boolean | isInterrupted()Returns a boolean indicating whether the receiver has a
pending interrupt request (true ) or not (
false )
VMThread vmt = this.vmThread;
if (vmt != null) {
return vmt.isInterrupted();
}
return false;
|
public final void | join()Blocks the current Thread (Thread.currentThread() ) until
the receiver finishes its execution and dies.
join(0, 0);
|
public final void | join(long millis)Blocks the current Thread (Thread.currentThread() ) until
the receiver finishes its execution and dies or the specified timeout
expires, whatever happens first.
join(millis, 0);
|
public final void | join(long millis, int nanos)Blocks the current Thread (Thread.currentThread() ) until
the receiver finishes its execution and dies or the specified timeout
expires, whatever happens first.
if (millis < 0 || nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException();
}
VMThread t;
t = this.vmThread;
if (t != null) {
synchronized (t) {
if (isAlive())
t.wait(millis, nanos);
}
}
|
void | parkFor(long nanos)Implementation of parkFor() . See {@link LangAccessImpl}.
This method must only be called when this is the current
thread.
VMThread vmt = vmThread;
if (vmt == null) {
// Running threads should always have an associated vmThread.
throw new AssertionError();
}
synchronized (vmt) {
switch (parkState) {
case ParkState.PREEMPTIVELY_UNPARKED: {
parkState = ParkState.UNPARKED;
break;
}
case ParkState.UNPARKED: {
long millis = nanos / 1000000;
nanos %= 1000000;
parkState = ParkState.PARKED;
try {
vmt.wait(millis, (int) nanos);
} catch (InterruptedException ex) {
interrupt();
} finally {
/*
* Note: If parkState manages to become
* PREEMPTIVELY_UNPARKED before hitting this
* code, it should left in that state.
*/
if (parkState == ParkState.PARKED) {
parkState = ParkState.UNPARKED;
}
}
break;
}
default /*parked*/: {
throw new AssertionError(
"shouldn't happen: attempt to repark");
}
}
}
|
void | parkUntil(long time)Implementation of parkUntil() . See {@link LangAccessImpl}.
This method must only be called when this is the current
thread.
VMThread vmt = vmThread;
if (vmt == null) {
// Running threads should always have an associated vmThread.
throw new AssertionError();
}
synchronized (vmt) {
/*
* Note: This conflates the two time bases of "wall clock"
* time and "monotonic uptime" time. However, given that
* the underlying system can only wait on monotonic time,
* it is unclear if there is any way to avoid the
* conflation. The downside here is that if, having
* calculated the delay, the wall clock gets moved ahead,
* this method may not return until well after the wall
* clock has reached the originally designated time. The
* reverse problem (the wall clock being turned back)
* isn't a big deal, since this method is allowed to
* spuriously return for any reason, and this situation
* can safely be construed as just such a spurious return.
*/
long delayMillis = time - System.currentTimeMillis();
if (delayMillis <= 0) {
parkState = ParkState.UNPARKED;
} else {
parkFor(delayMillis * 1000000);
}
}
|
public final void | resume()Resumes a suspended Thread. This is a no-op if the receiver was never
suspended, or suspended and already resumed. If the receiver is
suspended, however, makes it resume to the point where it was when it was
suspended.
checkAccess();
VMThread vmt = this.vmThread;
if (vmt != null) {
vmt.resume();
}
|
public void | run()Calls the run() method of the Runnable object the receiver
holds. If no Runnable is set, does nothing.
if (target != null) {
target.run();
}
|
public void | setContextClassLoader(java.lang.ClassLoader cl)Set the context ClassLoader for the receiver.
The RuntimePermission("setContextClassLoader")
is checked prior to setting the handler.
SecurityManager securityManager = System.getSecurityManager();
if (securityManager != null) {
securityManager.checkPermission(new RuntimePermission("setContextClassLoader"));
}
contextClassLoader = cl;
|
public final void | setDaemon(boolean isDaemon)Set if the receiver is a daemon Thread or not. This can only be done
before the Thread starts running.
checkAccess();
if (hasBeenStarted) {
throw new IllegalThreadStateException("Thread already started."); // TODO Externalize?
}
if (vmThread == null) {
daemon = isDaemon;
}
|
public static void | setDefaultUncaughtExceptionHandler(java.lang.Thread$UncaughtExceptionHandler handler)
Sets the default uncaught exception handler. This handler is invoked in
case any Thread dies due to an unhandled exception.
The RuntimePermission("setDefaultUncaughtExceptionHandler")
is checked prior to setting the handler.
SecurityManager securityManager = System.getSecurityManager();
if (securityManager != null) {
securityManager.checkPermission(new RuntimePermission ("setDefaultUncaughtExceptionHandler"));
}
Thread.defaultUncaughtHandler = handler;
|
private void | setInterruptAction(java.lang.Runnable action)Set the action to be executed when interruption, which is probably be
used to implement the interruptible channel. The action is null by
default. And if this method is invoked by passing in a non-null value,
this action's run() method will be invoked in interrupt() .
This is required internally by NIO, so even if it looks like it's
useless, don't delete it!
this.interruptAction = action;
|
public final void | setName(java.lang.String threadName)Sets the name of the Thread.
if (threadName == null) {
throw new NullPointerException();
}
checkAccess();
name = threadName;
VMThread vmt = this.vmThread;
if (vmt != null) {
/* notify the VM that the thread name has changed */
vmt.nameChanged(threadName);
}
|
public final void | setPriority(int priority)Sets the priority of the Thread. Note that the final priority set may not
be the parameter that was passed - it will depend on the receiver's
ThreadGroup. The priority cannot be set to be higher than the receiver's
ThreadGroup's maxPriority().
checkAccess();
if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
throw new IllegalArgumentException("Prioritiy out of range"); // TODO Externalize?
}
if (priority > group.getMaxPriority()) {
priority = group.getMaxPriority();
}
this.priority = priority;
VMThread vmt = this.vmThread;
if (vmt != null) {
vmt.setPriority(priority);
}
|
public void | setUncaughtExceptionHandler(java.lang.Thread$UncaughtExceptionHandler handler)
Sets the uncaught exception handler. This handler is invoked in case this
Thread dies due to an unhandled exception.
checkAccess();
uncaughtHandler = handler;
|
public static void | sleep(long time)Causes the thread which sent this message to sleep for the given interval
of time (given in milliseconds). The precision is not guaranteed - the
Thread may sleep more or less than requested.
Thread.sleep(time, 0);
|
public static void | sleep(long millis, int nanos)Causes the thread which sent this message to sleep for the given interval
of time (given in milliseconds and nanoseconds). The precision is not
guaranteed - the Thread may sleep more or less than requested.
VMThread.sleep(millis, nanos);
|
public synchronized void | start()Starts the new Thread of execution. The run() method of
the receiver will be called by the receiver Thread itself (and not the
Thread calling start() ).
if (hasBeenStarted) {
throw new IllegalThreadStateException("Thread already started."); // TODO Externalize?
}
hasBeenStarted = true;
VMThread.create(this, stackSize);
|
public final void | stop()Requests the receiver Thread to stop and throw ThreadDeath. The Thread is
resumed if it was suspended and awakened if it was sleeping, so that it
can proceed to throw ThreadDeath.
stop(new ThreadDeath());
|
public final synchronized void | stop(java.lang.Throwable throwable)Requests the receiver Thread to stop and throw the
throwable() . The Thread is resumed if it was suspended
and awakened if it was sleeping, so that it can proceed to throw the
throwable() .
SecurityManager securityManager = System.getSecurityManager();
if (securityManager != null) {
securityManager.checkAccess(this);
if (Thread.currentThread() != this) {
securityManager.checkPermission(new RuntimePermission("stopThread"));
}
}
if (throwable == null) {
throw new NullPointerException();
}
VMThread vmt = this.vmThread;
if (vmt != null) {
vmt.stop(throwable);
}
|
public final void | suspend()Suspends this Thread. This is a no-op if the receiver is suspended. If
the receiver isAlive() however, suspended it until
resume() is sent to it. Suspend requests are not queued, which
means that N requests are equivalent to just one - only one resume
request is needed in this case.
checkAccess();
VMThread vmt = this.vmThread;
if (vmt != null) {
vmt.suspend();
}
|
public java.lang.String | toString()Returns a string containing a concise, human-readable description of the
Thread. It includes the Thread's name, priority, and group name.
return "Thread[" + name + "," + priority + "," + group.getName() + "]";
|
void | unpark()Implementation of unpark() . See {@link LangAccessImpl}.
VMThread vmt = vmThread;
if (vmt == null) {
/*
* vmThread is null before the thread is start()ed. In
* this case, we just go ahead and set the state to
* PREEMPTIVELY_UNPARKED. Since this happens before the
* thread is started, we don't have to worry about
* synchronizing with it.
*/
parkState = ParkState.PREEMPTIVELY_UNPARKED;
return;
}
synchronized (vmt) {
switch (parkState) {
case ParkState.PREEMPTIVELY_UNPARKED: {
/*
* Nothing to do in this case: By definition, a
* preemptively unparked thread is to remain in
* the preemptively unparked state if it is told
* to unpark.
*/
break;
}
case ParkState.UNPARKED: {
parkState = ParkState.PREEMPTIVELY_UNPARKED;
break;
}
default /*parked*/: {
parkState = ParkState.UNPARKED;
vmt.notifyAll();
break;
}
}
}
|
public static void | yield()Causes the calling Thread to yield execution time to another Thread that
is ready to run. The actual scheduling is implementation-dependent.
VMThread.yield();
|