kvm线程-006-线程状态-THREAD_ACTIVE

本文介绍线程状态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-线程切换中有介绍

这个方法的调用点有:

  1. Java_java_lang_Thread_sleep ,此处在kvm线程-003中有介绍
  2. Java_com_sun_cldc_io_Waiter_waitForIO // 异步i/o,这里不介绍
  3. Java_java_lang_Thread_start
  4. interruptThread
  5. removeMonitorWait // 这个后文介绍

Java_java_lang_Thread_start

此处的代码如下:

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++;


}

interruptThread

在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
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值