本文介绍线程状态THREAD_ACTIVE的使用.设置线程状态THREAD_ACTIVE的地方有:
InitializeThreading,这点在kvm启动流程-006 中有详细介绍.
resumeThread,其代码如下:
void resumeThread(THREAD thisThread)
{
// 如果状态不是THREAD_SUSPENDED,则抛出异常
if (!(thisThread->state & THREAD_SUSPENDED)) {
fatalError(KVM_MSG_ATTEMPTING_TO_RESUME_NONSUSPENDED_THREAD);
}
/* 设置状态为THREAD_ACTIVE */
thisThread->state = THREAD_ACTIVE;
if (thisThread == CurrentThread) { // 如果thisThread为CurrentThread,则抛出异常,此时是错误情况
fatalError(KVM_MSG_ATTEMPTING_TO_RESUME_CURRENT_THREAD);
} else {
/* 加入到RunnableThreads队列中*/
addThreadToQueue(&RunnableThreads, thisThread, AT_END);
}
}
其中, addThreadToQueue在kvm线程-004-线程切换中有介绍
这个方法的调用点有:
此处的代码如下:
void Java_java_lang_Thread_start(void)
{
START_TEMPORARY_ROOTS
DECLARE_TEMPORARY_ROOT(JAVATHREAD, javaThread,
popStackAsType(JAVATHREAD));
// 1.构建vmthread
DECLARE_TEMPORARY_ROOT(THREAD, VMthread, getVMthread(&javaThread));
/* Check if a separate Runnable object has been provided */
INSTANCE target =
(javaThread->target) ? javaThread->target : (INSTANCE)javaThread;
METHOD thisMethod;
/* 2. 如果状态不是THREAD_JUST_BORN,则抛出异常 */
if (VMthread->state != THREAD_JUST_BORN) {
raiseException(IllegalThreadStateException);
goto done;
}
/* 3. 找到run方法,如果run方法不存在,则抛出异常 */
thisMethod =
lookupMethod((CLASS)target->ofClass, runNameAndType,
target->ofClass);
if (thisMethod == NULL) {
raiseException("java/lang/Error");
goto done;
}
/* 4. 初始化栈帧 */
initThreadBehavior(VMthread, thisMethod, (OBJECT)target);
/* 5. 设置参数,因为run是一个多态方法,因此必须有一个this参数 */
*(INSTANCE *)&VMthread->stack->cells[0] = target;
/* 6.启动线程 */
startThread(VMthread);
// 7. 加入到RunnableThreads中,上文有介绍
resumeThread(VMthread);
done:
END_TEMPORARY_ROOTS
}
其中第4步如下:
void initThreadBehavior(THREAD thisThread, METHOD thisMethod, OBJECT syncObjectArg)
{
START_TEMPORARY_ROOTS
/* Protect the syncObject argument from garbage collection */
/*
* OBJECT syncObject = (
syncObject = syncObjectArg,
TemporaryRoots[TemporaryRootsLength++].cellp = (cell *)&syncObject, \
syncObject)
*/
DECLARE_TEMPORARY_ROOT(OBJECT, syncObject, syncObjectArg);
/*
* 注意,启动时thisthread==currentThread。下面这段代码的效率稍低,但不值得为一次性的案例费心去修复。
*/
// 1. 保存当前线程的状态
THREAD current = CurrentThread;
if (current != NULL) {
storeExecutionEnvironment(current);
}
CurrentThread = thisThread;
// 设置栈帧
setSP((thisThread->stack->cells - 1) + thisMethod->argCount);
setFP(NULL);
setIP(KILLTHREAD);
pushFrame(thisMethod);
if (thisMethod->accessFlags & ACC_SYNCHRONIZED) { // 如果是同步方法的话
getFP()->syncObject = syncObject;
pushFrame(RunCustomCodeMethod);
pushStackAsType(CustomCodeCallbackFunction,
initThreadBehaviorFromThread); // 进行同步,此处后文介绍
} else {
getFP()->syncObject = NULL;
}
// 保存thisThread的状态
storeExecutionEnvironment(thisThread);
if (current) {
// 恢复之前CurrentThread的状态
loadExecutionEnvironment(current);
}
// 恢复CurrentThread
CurrentThread = current;
END_TEMPORARY_ROOTS
}
关于栈帧的部分,在kvm启动流程-006中有介绍.
第六步,启动线程的代码如下:
void startThread(THREAD thisThread)
{
/* 设置状态为THREAD_SUSPENDED*/
thisThread->state = THREAD_SUSPENDED;
AliveThreadCount++;
}
在kvm中,Thread的interrupt方法实现如下:
public void interrupt() {
interrupt0();
}
private native void interrupt0();
void Java_java_lang_Thread_interrupt0(void)
{
START_TEMPORARY_ROOTS
DECLARE_TEMPORARY_ROOT(JAVATHREAD, javaThread,
popStackAsType(JAVATHREAD));
DECLARE_TEMPORARY_ROOT(THREAD, VMthread, getVMthread(&javaThread));
if (VMthread->state != THREAD_JUST_BORN &&
VMthread->state != THREAD_DEAD) {
interruptThread(VMthread);
}
END_TEMPORARY_ROOTS
}
interruptThread的代码如下:
void interruptThread(THREAD thread) {
bool_t sleeping = FALSE;
bool_t waiting = FALSE;
if (inTimerQueue(thread)) { // 1. 如果是在sleep 中,则从等待队列移除,
removePendingAlarm(thread);
sleeping = TRUE;
}
// 2. 如果是在等待唤醒
if (thread->state & THREAD_CONVAR_WAIT) {
MONITOR monitor = thread->monitor;
removeFromQueue(&monitor->condvar_waitq, thread); // 将该线程从等待唤醒队列中删除
addMonitorWait(monitor, thread); // 加入到等待mointer队列中
waiting = TRUE;
}
if (sleeping || waiting) {
thread->pendingException = (char*)InterruptedException; // 设置异常
if (!waiting) {
resumeThread(thread); // 恢复线程 ,此处在上文有介绍
}
} else { // 其他情况
thread->isPendingInterrupt = TRUE;
}
}
关于interruptThread,如果线程是在sleep,等待唤醒时,则会设置pendingException.则此时会在invokeNativeFunction方法中处理(interrupt0是本地方法), invokeNativeFunction在kvm 本地方法实现 中有介绍:
if (CurrentThread) {
/* Remember to reset the native LP so that garbage collector */
/* doesn't have to do redundant work */
CurrentThread->nativeLp = NULL;
/* Check for pending exceptions (KNI_Throw) */
if (CurrentThread->pendingException) {
const char* pending = CurrentThread->pendingException;
CurrentThread->pendingException = NULL;
if (CurrentThread->exceptionMessage) {
const char* message = CurrentThread->exceptionMessage;
CurrentThread->exceptionMessage = NULL;
raiseExceptionWithMessage(pending, message);
} else {
raiseException(pending);
}
}
}
对于当前情况,则最终会调用raiseException方法,代码如下:
void raiseException(const char* exceptionClassName)
{
#if INCLUDEDEBUGCODE
/* Turn off the allocation guard */
NoAllocation = 0;
#endif /* INCLUDEDEBUGCODE */
THROW(getExceptionInstance(exceptionClassName, NULL))
}
则此时会进入异常处理流程.关于这点,就不展开了.
关于interruptThread的案例网上有很多:
但是没有同步的案例,此处提供一下:
public class InterruptTest {
public static volatile Object sync = new Object();
public static void main(String[] args) {
Thread thread = new Thread("thread"){
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" in run");
synchronized(sync){
try {
sync.wait();
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()+" Interrupted");
}
}
}
};
thread.start();
thread.interrupt();
}
}
输出结果为:
thread in run
thread Interrupted