线程的状态
常见的线程状态
- 初始状态(NEW):线程被构建,没有调用start方法
- 运行状态(RUNNABLE):JAVA线程将操作系统中的就绪和运行两中状态统称为“运行中”
- 阻塞状态(blocked):线程阻塞于锁
- 等待状态(WAITING):当前线程需要等待其他线程做出一些特定动作(通知或者中断)
- 超时等待状态(TIME_WAITING):不同于WAITING,可以在制定时间返回
- 终止状态(TERMINTED):当前线程已经执行完毕
状态的流转
线程的常用方法
1、初始化线程
初始化一个线程,由父线程进行空间分配,子线程继承了父线程的daemon、priority,以及可以继承的ThreadLocal,同时分配一个唯一的标识的线程id
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name;
// 当前线程为父线程
Thread parent = currentThread();
SecurityManager security = System.getSecurityManager();
if (g == null) {
if (security != null) {
g = security.getThreadGroup();
}
if (g == null) {
g = parent.getThreadGroup();
}
}
g.checkAccess();
/*
* Do we have the required permissions?
*/
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
g.addUnstarted();
this.group = g;
//获取父线程的优先级和是否是守护线程
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
this.target = target;
setPriority(priority);
//判断是否继承父线程的localmap
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
//分配一个线程号
tid = nextThreadID();
}
2、启动线程
/**
* Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.
* The result is that two threads are running concurrently: the current thread (which returns from the call to the
* start() method) and the other thread (which executes its run() method).
* It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has
* completed execution.
*
* @exception IllegalThreadStateException if the thread was already
* started.
* @see #run()
* @see #stop()
*/
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
private native void start0();
3、中断
3.1、interrupt
- 除非当前线程正在中断自己(这总是允许的),否则将调用该线程的checkAccess方法,这可能导致抛出SecurityException。
- 如果当前线程被blocked,再调用 the wait(), wait(long), or wait(long, int)methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long,int),interrupt(),中断标识被清除,同时抛出InterruptedException
- 如果这个线程在I/O操作中被InterruptibleChannel阻塞,那么通道将被关闭,线程的中断状态将被设置,并且该线程将接收到一个java.nio.channels.ClosedByInterruptException。
- 如果这个线程在java.nio.channels中被阻塞。然后线程的中断状态将被设置,它将立即从选择操作中返回,可能带有一个非零值,就像调用了选择器的唤醒方法一样。
- 如果前面的条件都不成立,那么这个线程的中断状态将被设置。
public void interrupt() {
if (this != Thread.currentThread())
checkAccess();
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0(); // Just to set the interrupt flag
b.interrupt(this);
return;
}
}
interrupt0();
}
private native void interrupt0();
3.2、interrupted
返回当前线程是否被中断过,并当前线程的中断标识进行复位。
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
private native boolean isInterrupted(boolean ClearInterrupted);
3.3 isInterrupted
返回当前线程是否被中断过
public boolean isInterrupted() {
return isInterrupted(false);
}
4、暂停suspend、恢复resume、终止stop
调用了suspend方法后,线程不会释放已经占有的资源,容易引起死锁;同样,stop方法也不保证释放所有的资源正常释放
@Deprecated
public final void suspend() {
checkAccess();
suspend0();
}
@Deprecated
public final void resume() {
checkAccess();
resume0();
}
@Deprecated
public final void stop() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
checkAccess();
if (this != Thread.currentThread()) {
security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
}
}
// A zero status value corresponds to "NEW", it can't change to
// not-NEW because we hold the lock.
if (threadStatus != 0) {
resume(); // Wake up thread if it was suspended; no-op otherwise
}
// The VM can handle all thread states
stop0(new ThreadDeath());
}
5、join
等待线程死亡的时间最多为毫秒。超时为0意味着永远等待。
public final synchronized void join(long millis) throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
关于面试哪些事,欢迎关注公众号“程序员ZZ的源码”