Thread
Java通过java.lang.Thread类来描述一个线程。
Java除了可以通过实现java.lang.Runnable接口创建线程,还可以继承java.lang.Thread类。和实现java.lang.Runnable接口创建线程需要实现run方法一样,通过继承java.lang.Thread类来创建线程也需要重写run方法。
官方的一个例子:
class PrimeThread extends Thread { long minPrime; PrimeThread(long minPrime) { this.minPrime = minPrime; } public void run() { // compute primes larger than minPrime . . . } }启动这个线程也很简单:
Thread t = new PrimeThread(); t.start();Thread(java.lang.Thread)在jdk\src\share\classes\java\lang目录下。提供了很多和线程相关的方法,其中有部分方法是本地方法,本地方法部分实现Thread.c在jdk\src\share\native\java\lang目录下。
方法
Thread(java.lang.Thread)提供了很多和线程相关的方法。run,start方法是经常用到的方法,run方法用于实现一个线程运行的具体逻辑,start用于启动一个线程,其他常用的方法如currentThread、yield、sleep、exit、stop、interrupt、interrupted、isInterrupted、destroy、isAlive、suspend、resume、setPriority、getPriority、join、setDaemon、isDaemon,不过有些方法已经被@Deprecated掉了,不建议使用这些@Deprecated掉了的方法。
普通方法
private static synchronized int nextThreadNum()
在创建一个线程时如果没有指定一个名称时,会自动指定一个线程名Thread-线程号。
private static synchronized long nextThreadID()
分配线程id(tid)
blockedOn
sleep
init
init
clone
start
run
exit
stop
stop
stop1
interrupt
interrupted
isInterrupted
destroy
suspend
resume
setPriority
getPriority
setName
getName
getThreadGroup
activeCount
enumerate
join
join
join
dumpStack
setDaemon
isDaemon
checkAccess
toString
getContextClassLoader
setContextClassLoader
getStackTrace
getAllStackTraces
isCCLOverridden
auditSubclass
getId
getState
setDefaultUncaughtExceptionHandler
getDefaultUncaughtExceptionHandler
getUncaughtExceptionHandler
setUncaughtExceptionHandler
dispatchUncaughtException
本地方法
一般来说,本地方法实现采用jni方式,比如registerNatives方法,在Java中,在jdk\src\share\classes\java\lang目录下,声明如下:
/* Make sure registerNatives is the first thing <clinit> does. */ private static native void registerNatives(); |
在实现Thread.c中,在jdk\src\share\native\java\lang目录下,有类似实现:
JNIEXPORT void JNICALL Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls) { (*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods)); } |
但Thread,除了registerNatives方法,其他本地方法有些不一样,其他本地方法都是通过registerNatives方法进行注册。
registerNatives
currentThread
yield
sleep
start0
isInterrupted
isAlive
countStackFrames
holdsLock
dumpThreads
getThreads
setPriority0
stop0
suspend0
resume0
interrupt0
本地方法解释
registerNatives
在Java中的声明如下:
/* Make sure registerNatives is the first thing <clinit> does. */ private static native void registerNatives(); |
实际的实现:
JNIEXPORT void JNICALL Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls) { (*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods)); } |
这里通过jni的方式对其他的本地方法进行了注册
static JNINativeMethod methods[] = { {"start0", "()V", (void *)&JVM_StartThread}, {"stop0", "(" OBJ ")V", (void *)&JVM_StopThread}, {"isAlive", "()Z", (void *)&JVM_IsThreadAlive}, {"suspend0", "()V", (void *)&JVM_SuspendThread}, {"resume0", "()V", (void *)&JVM_ResumeThread}, {"setPriority0", "(I)V", (void *)&JVM_SetThreadPriority}, {"yield", "()V", (void *)&JVM_Yield}, {"sleep", "(J)V", (void *)&JVM_Sleep}, {"currentThread", "()" THD, (void *)&JVM_CurrentThread}, {"countStackFrames", "()I", (void *)&JVM_CountStackFrames}, {"interrupt0", "()V", (void *)&JVM_Interrupt}, {"isInterrupted", "(Z)Z", (void *)&JVM_IsInterrupted}, {"holdsLock", "(" OBJ ")Z", (void *)&JVM_HoldsLock}, {"getThreads", "()[" THD, (void *)&JVM_GetAllThreads}, {"dumpThreads", "([" THD ")[[" STE, (void *)&JVM_DumpThreads}, }; |
currentThread
在Java中的声明如下:
public static native Thread currentThread(); |
从上面的本地方法注册可以看出,对应的实现为:
JVM_CurrentThread |
具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:
JVM_ENTRY(jobject, JVM_CurrentThread(JNIEnv* env, jclass threadClass)) JVMWrapper("JVM_CurrentThread"); oop jthread = thread->threadObj(); assert (thread != NULL, "no current thread!"); return JNIHandles::make_local(env, jthread); JVM_END |
Java Thread 启动线程
Java Thread(java.lang.Thread)类提供了一个启动线程的方法。该方法是这样的:
public synchronized void start() |
该方法调用了一个native方法,通过这个native方法来启动线程,这个本地方法声明如下:
private native void start0(); |
该方法注册的对应实现为JVM_StartThread,在hotspot\src\share\vm\prims目录下的jvm.cpp,内部实现如下:
JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread)) JVMWrapper("JVM_StartThread"); JavaThread *native_thread = NULL;
// We cannot hold the Threads_lock when we throw an exception, // due to rank ordering issues. Example: we might need to grab the // Heap_lock while we construct the exception. bool throw_illegal_thread_state = false;
// We must release the Threads_lock before we can post a jvmti event // in Thread::start. { // Ensure that the C++ Thread and OSThread structures aren't freed before // we operate. MutexLocker mu(Threads_lock);
// Since JDK 5 the java.lang.Thread threadStatus is used to prevent // re-starting an already started thread, so we should usually find // that the JavaThread is null. However for a JNI attached thread // there is a small window between the Thread object being created // (with its JavaThread set) and the update to its threadStatus, so we // have to check for this if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) { throw_illegal_thread_state = true; } else { // We could also check the stillborn flag to see if this thread was already stopped, but // for historical reasons we let the thread detect that itself when it starts running
jlong size = java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread)); // Allocate the C++ Thread structure and create the native thread. The // stack size retrieved from java is signed, but the constructor takes // size_t (an unsigned type), so avoid passing negative values which would // result in really large stacks. size_t sz = size > 0 ? (size_t) size : 0; native_thread = new JavaThread(&thread_entry, sz);
// At this point it may be possible that no osthread was created for the // JavaThread due to lack of memory. Check for this situation and throw // an exception if necessary. Eventually we may want to change this so // that we only grab the lock if the thread was created successfully - // then we can also do this check and throw the exception in the // JavaThread constructor. if (native_thread->osthread() != NULL) { // Note: the current thread is not being used within "prepare". native_thread->prepare(jthread); } } }
if (throw_illegal_thread_state) { THROW(vmSymbols::java_lang_IllegalThreadStateException()); }
assert(native_thread != NULL, "Starting null thread?");
if (native_thread->osthread() == NULL) { // No one should hold a reference to the 'native_thread'. delete native_thread; if (JvmtiExport::should_post_resource_exhausted()) { JvmtiExport::post_resource_exhausted( JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS, "unable to create new native thread"); } THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "unable to create new native thread"); }
Thread::start(native_thread);
JVM_END |
完整代码需要展开来才能看:
// no define ASSERT extern "C" { void JNICALL JVM_StartThread(JNIEnv* env, jobject jthread) { JavaThread* thread=JavaThread::thread_from_jni_environment(env); ThreadInVMfromNative __tiv(thread);
/* do nothing */ HandleMarkCleaner __hm(thread); Thread* THREAD = thread; /* begin of body */
; JavaThread *native_thread = NULL;
// We cannot hold the Threads_lock when we throw an exception, // due to rank ordering issues. Example: we might need to grab the // Heap_lock while we construct the exception. bool throw_illegal_thread_state = false;
// We must release the Threads_lock before we can post a jvmti event // in Thread::start. { // Ensure that the C++ Thread and OSThread structures aren't freed before // we operate. MutexLocker mu(Threads_lock);
// Since JDK 5 the java.lang.Thread threadStatus is used to prevent // re-starting an already started thread, so we should usually find // that the JavaThread is null. However for a JNI attached thread // there is a small window between the Thread object being created // (with its JavaThread set) and the update to its threadStatus, so we // have to check for this if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) { throw_illegal_thread_state = true; } else { // We could also check the stillborn flag to see if this thread was already stopped, but // for historical reasons we let the thread detect that itself when it starts running
jlong size = java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread)); // Allocate the C++ Thread structure and create the native thread. The // stack size retrieved from java is signed, but the constructor takes // size_t (an unsigned type), so avoid passing negative values which would // result in really large stacks. size_t sz = size > 0 ? (size_t) size : 0; native_thread = new JavaThread(&thread_entry, sz);
// At this point it may be possible that no osthread was created for the // JavaThread due to lack of memory. Check for this situation and throw // an exception if necessary. Eventually we may want to change this so // that we only grab the lock if the thread was created successfully - // then we can also do this check and throw the exception in the // JavaThread constructor. if (native_thread->osthread() != NULL) { // Note: the current thread is not being used within "prepare". native_thread->prepare(jthread); } } }
if (throw_illegal_thread_state) { THROW(vmSymbols::java_lang_IllegalThreadStateException()); }
assert(native_thread != NULL, "Starting null thread?");
if (native_thread->osthread() == NULL) { // No one should hold a reference to the 'native_thread'. delete native_thread; if (JvmtiExport::should_post_resource_exhausted()) { JvmtiExport::post_resource_exhausted( JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS, "unable to create new native thread"); } THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "unable to create new native thread"); }
Thread::start(native_thread);
} } |
该方法创建了一个JavaThread线程,在创建JavaThread线程时传入了两个参数,第一个参数为线程执行的函数入口:entry_point(ThreadFunction),第二个参数表示线程栈空间大小。
thread_entry
在hotspot\src\share\vm\prims目录下的jvm.cpp
static void thread_entry(JavaThread* thread, TRAPS) { HandleMark hm(THREAD); Handle obj(THREAD, thread->threadObj()); JavaValue result(T_VOID); JavaCalls::call_virtual(&result, obj, KlassHandle(THREAD, SystemDictionary::Thread_klass()), vmSymbols::run_method_name(), vmSymbols::void_method_signature(), THREAD); } |
native_thread = new JavaThread(&thread_entry, sz); |
这个JavaThread构造实现代码如下:(在\hotspot\src\share\vm\runtime目录下的thread.cpp)
JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) : Thread() #ifndef SERIALGC , _satb_mark_queue(&_satb_mark_queue_set), _dirty_card_queue(&_dirty_card_queue_set) #endif // !SERIALGC { if (TraceThreadEvents) { tty->print_cr("creating thread %p", this); } initialize(); _jni_attach_state = _not_attaching_via_jni; set_entry_point(entry_point); // Create the native thread itself. // %note runtime_23 os::ThreadType thr_type = os::java_thread; thr_type = entry_point == &compiler_thread_entry ? os::compiler_thread : os::java_thread; os::create_thread(this, thr_type, stack_sz);
// The _osthread may be NULL here because we ran out of memory (too many threads active). // We need to throw and OutOfMemoryError - however we cannot do this here because the caller // may hold a lock and all locks must be unlocked before throwing the exception (throwing // the exception consists of creating the exception object & initializing it, initialization // will leave the VM via a JavaCall and then all locks must be unlocked). // // The thread is still suspended when we reach here. Thread must be explicit started // by creator! Furthermore, the thread must also explicitly be added to the Threads list // by calling Threads:add. The reason why this is not done here, is because the thread // object must be fully initialized (take a look at JVM_Start) } |
这里调用os::create_thread创建了线程,该方法声明如下:
static bool create_thread(Thread* thread, ThreadType thr_type, size_t stack_size = 0); |
具体实现不同平台不一样,代码实现在hotspot\src\os\solaris\vm的os_solaris.cpp下,其他平台在src\os\solaris\vm\os_solaris.cpp、hotspot\src\os\windows\vm\os_windows.cpp、hotspot\src\os\linux\vm\os_linux.cpp、hotspot\src\os\bsd\vm\os_bsd.cpp下面。
Linux:
bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { assert(thread->osthread() == NULL, "caller responsible");
// Allocate the OSThread object OSThread* osthread = new OSThread(NULL, NULL); if (osthread == NULL) { return false; }
// set the correct thread state osthread->set_thread_type(thr_type);
// Initial state is ALLOCATED but not INITIALIZED osthread->set_state(ALLOCATED);
thread->set_osthread(osthread);
// init thread attributes pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
// stack size if (os::Linux::supports_variable_stack_size()) { // calculate stack size if it's not specified by caller if (stack_size == 0) { stack_size = os::Linux::default_stack_size(thr_type);
switch (thr_type) { case os::java_thread: // Java threads use ThreadStackSize which default value can be // changed with the flag -Xss assert (JavaThread::stack_size_at_create() > 0, "this should be set"); stack_size = JavaThread::stack_size_at_create(); break; case os::compiler_thread: if (CompilerThreadStackSize > 0) { stack_size = (size_t)(CompilerThreadStackSize * K); break; } // else fall through: // use VMThreadStackSize if CompilerThreadStackSize is not defined case os::vm_thread: case os::pgc_thread: case os::cgc_thread: case os::watcher_thread: if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K); break; } }
stack_size = MAX2(stack_size, os::Linux::min_stack_allowed); pthread_attr_setstacksize(&attr, stack_size); } else { // let pthread_create() pick the default value. }
// glibc guard page pthread_attr_setguardsize(&attr, os::Linux::default_guard_size(thr_type));
ThreadState state;
{ // Serialize thread creation if we are running with fixed stack LinuxThreads bool lock = os::Linux::is_LinuxThreads() && !os::Linux::is_floating_stack(); if (lock) { os::Linux::createThread_lock()->lock_without_safepoint_check(); }
pthread_t tid; int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);
pthread_attr_destroy(&attr);
if (ret != 0) { if (PrintMiscellaneous && (Verbose || WizardMode)) { perror("pthread_create()"); } // Need to clean up stuff we've allocated so far thread->set_osthread(NULL); delete osthread; if (lock) os::Linux::createThread_lock()->unlock(); return false; }
// Store pthread info into the OSThread osthread->set_pthread_id(tid);
// Wait until child thread is either initialized or aborted { Monitor* sync_with_child = osthread->startThread_lock(); MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag); while ((state = osthread->get_state()) == ALLOCATED) { sync_with_child->wait(Mutex::_no_safepoint_check_flag); } }
if (lock) { os::Linux::createThread_lock()->unlock(); } }
// Aborted due to thread limit being reached if (state == ZOMBIE) { thread->set_osthread(NULL); delete osthread; return false; }
// The thread is returned suspended (in state INITIALIZED), // and is started higher up in the call chain assert(state == INITIALIZED, "race condition"); return true; } |
最终在这里调用了pthread_create创建线程,注意第三个参数java_start, 这个是线程执行的回调函数,也就是传给pthread_create的start routine,在这个函数里调用的Java Thread线程的run方法,在这里设置线程为初始状态INITIALIZED,并进入阻塞等待直到后面调用os::start_thread后才能继续运行。具体代码如下:
具体实现不同平台不一样,代码实现在hotspot\src\os\solaris\vm的os_solaris.cpp下,其他平台在src\os\solaris\vm\os_solaris.cpp、hotspot\src\os\windows\vm\os_windows.cpp、hotspot\src\os\linux\vm\os_linux.cpp、hotspot\src\os\bsd\vm\os_bsd.cpp下面。
Linux:
// Thread start routine for all newly created threads static void *java_start(Thread *thread) { // Try to randomize the cache line index of hot stack frames. // This helps when threads of the same stack traces evict each other's // cache lines. The threads can be either from the same JVM instance, or // from different JVM instances. The benefit is especially true for // processors with hyperthreading technology. static int counter = 0; int pid = os::current_process_id(); alloca(((pid ^ counter++) & 7) * 128);
ThreadLocalStorage::set_thread(thread);
OSThread* osthread = thread->osthread(); Monitor* sync = osthread->startThread_lock();
// non floating stack LinuxThreads needs extra check, see above if (!_thread_safety_check(thread)) { // notify parent thread MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag); osthread->set_state(ZOMBIE); sync->notify_all(); return NULL; }
// thread_id is kernel thread id (similar to Solaris LWP id) osthread->set_thread_id(os::Linux::gettid());
if (UseNUMA) { int lgrp_id = os::numa_get_group_id(); if (lgrp_id != -1) { thread->set_lgrp_id(lgrp_id); } } // initialize signal mask for this thread os::Linux::hotspot_sigmask(thread);
// initialize floating point control register os::Linux::init_thread_fpu_state();
// handshaking with parent thread { MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag);
// notify parent thread osthread->set_state(INITIALIZED); sync->notify_all();
// wait until os::start_thread() while (osthread->get_state() == INITIALIZED) { sync->wait(Mutex::_no_safepoint_check_flag); } }
// call one more level start routine thread->run();
return 0; } |
并调用Thread::start方法启动线程(JavaThread线程),这个方法实现在hotspot\src\share\vm\runtime目录下的thread.cpp。
void Thread::start(Thread* thread) { trace("start", thread); // Start is different from resume in that its safety is guaranteed by context or // being called from a Java method synchronized on the Thread object. if (!DisableStartThread) { if (thread->is_Java_thread()) { // Initialize the thread state to RUNNABLE before starting this thread. // Can not set it after the thread started because we do not know the // exact thread state at that time. It could be in MONITOR_WAIT or // in SLEEPING or some other state. java_lang_Thread::set_thread_status(((JavaThread*)thread)->threadObj(), java_lang_Thread::RUNNABLE); } os::start_thread(thread); } } |
这里调用了os::start_thread来启动线程,该方法实现在hotspot\src\share\vm\runtime目录下的os.cpp
void os::start_thread(Thread* thread) { // guard suspend/resume MutexLockerEx ml(thread->SR_lock(), Mutex::_no_safepoint_check_flag); OSThread* osthread = thread->osthread(); osthread->set_state(RUNNABLE); pd_start_thread(thread); } |
最后调用pd_start_thread方法启动,代码实现在hotspot\src\os\solaris\vm的os_solaris.cpp下,其他平台在src\os\solaris\vm\os_solaris.cpp、hotspot\src\os\windows\vm\os_windows.cpp、hotspot\src\os\linux\vm\os_linux.cpp、hotspot\src\os\bsd\vm\os_bsd.cpp下面。
Solaris:
void os::pd_start_thread(Thread* thread) { int status = thr_continue(thread->osthread()->thread_id()); assert_status(status == 0, status, "thr_continue failed"); } |
Linux:
void os::pd_start_thread(Thread* thread) { OSThread * osthread = thread->osthread(); assert(osthread->get_state() != INITIALIZED, "just checking"); Monitor* sync_with_child = osthread->startThread_lock(); MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag); sync_with_child->notify(); } |
JavaThread与Thread的继承关系:
enum ThreadType { vm_thread, cgc_thread, // Concurrent GC thread pgc_thread, // Parallel GC thread java_thread, compiler_thread, watcher_thread, os_thread };
yield
在Java中的声明如下:
public static native void yield(); |
从上面的本地方法注册可以看出,对应的实现为:
JVM_Yield |
具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:
JVM_ENTRY(void, JVM_Yield(JNIEnv *env, jclass threadClass)) JVMWrapper("JVM_Yield"); if (os::dont_yield()) return; #ifndef USDT2 HS_DTRACE_PROBE0(hotspot, thread__yield); #else /* USDT2 */ HOTSPOT_THREAD_YIELD(); #endif /* USDT2 */ // When ConvertYieldToSleep is off (default), this matches the classic VM use of yield. // Critical for similar threading behaviour if (ConvertYieldToSleep) { os::sleep(thread, MinSleepInterval, false); } else { os::yield(); } JVM_END |
sleep
在Java中的声明如下:
public static native void sleep(long millis) throws InterruptedException; |
sleep指定时间(毫秒数)。可以指定为0,如果开启了ConvertSleepToYield参数,相当于yield。否则,设置对应的OS Thread的状态为SLEEPING,并调用os::sleep函数,之后恢复OS Thread的状态为SLEEPING之前的状态。
从上面的本地方法注册可以看出,对应的实现为:
JVM_Sleep |
具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:
JVM_ENTRY(void, JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis)) JVMWrapper("JVM_Sleep"); if (millis < 0) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative"); } if (Thread::is_interrupted (THREAD, true) && !HAS_PENDING_EXCEPTION) { THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted"); } // Save current thread state and restore it at the end of this block. // And set new thread state to SLEEPING. JavaThreadSleepState jtss(thread); #ifndef USDT2 HS_DTRACE_PROBE1(hotspot, thread__sleep__begin, millis); #else /* USDT2 */ HOTSPOT_THREAD_SLEEP_BEGIN( millis); #endif /* USDT2 */ if (millis == 0) { // When ConvertSleepToYield is on, this matches the classic VM implementation of // JVM_Sleep. Critical for similar threading behaviour (Win32) // It appears that in certain GUI contexts, it may be beneficial to do a short sleep // for SOLARIS if (ConvertSleepToYield) { os::yield(); } else { ThreadState old_state = thread->osthread()->get_state(); thread->osthread()->set_state(SLEEPING); os::sleep(thread, MinSleepInterval, false); thread->osthread()->set_state(old_state); } } else { ThreadState old_state = thread->osthread()->get_state(); thread->osthread()->set_state(SLEEPING); if (os::sleep(thread, millis, true) == OS_INTRPT) { // An asynchronous exception (e.g., ThreadDeathException) could have been thrown on // us while we were sleeping. We do not overwrite those. if (!HAS_PENDING_EXCEPTION) { #ifndef USDT2 HS_DTRACE_PROBE1(hotspot, thread__sleep__end,1); #else /* USDT2 */ HOTSPOT_THREAD_SLEEP_END( 1); #endif /* USDT2 */ // TODO-FIXME: THROW_MSG returns which means we will not call set_state() // to properly restore the thread state. That's likely wrong. THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted"); } } thread->osthread()->set_state(old_state); } #ifndef USDT2 HS_DTRACE_PROBE1(hotspot, thread__sleep__end,0); #else /* USDT2 */ HOTSPOT_THREAD_SLEEP_END( 0); #endif /* USDT2 */ JVM_END
start0
在Java中的声明如下:
private native void start0(); |
从上面的本地方法注册可以看出,对应的实现为:
JVM_StartThread |
具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:
JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread)) JVMWrapper("JVM_StartThread"); JavaThread *native_thread = NULL;
// We cannot hold the Threads_lock when we throw an exception, // due to rank ordering issues. Example: we might need to grab the // Heap_lock while we construct the exception. bool throw_illegal_thread_state = false;
// We must release the Threads_lock before we can post a jvmti event // in Thread::start. { // Ensure that the C++ Thread and OSThread structures aren't freed before // we operate. MutexLocker mu(Threads_lock);
// Since JDK 5 the java.lang.Thread threadStatus is used to prevent // re-starting an already started thread, so we should usually find // that the JavaThread is null. However for a JNI attached thread // there is a small window between the Thread object being created // (with its JavaThread set) and the update to its threadStatus, so we // have to check for this if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) { throw_illegal_thread_state = true; } else { // We could also check the stillborn flag to see if this thread was already stopped, but // for historical reasons we let the thread detect that itself when it starts running
jlong size = java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread)); // Allocate the C++ Thread structure and create the native thread. The // stack size retrieved from java is signed, but the constructor takes // size_t (an unsigned type), so avoid passing negative values which would // result in really large stacks. size_t sz = size > 0 ? (size_t) size : 0; native_thread = new JavaThread(&thread_entry, sz);
// At this point it may be possible that no osthread was created for the // JavaThread due to lack of memory. Check for this situation and throw // an exception if necessary. Eventually we may want to change this so // that we only grab the lock if the thread was created successfully - // then we can also do this check and throw the exception in the // JavaThread constructor. if (native_thread->osthread() != NULL) { // Note: the current thread is not being used within "prepare". native_thread->prepare(jthread); } } }
if (throw_illegal_thread_state) { THROW(vmSymbols::java_lang_IllegalThreadStateException()); }
assert(native_thread != NULL, "Starting null thread?");
if (native_thread->osthread() == NULL) { // No one should hold a reference to the 'native_thread'. delete native_thread; if (JvmtiExport::should_post_resource_exhausted()) { JvmtiExport::post_resource_exhausted( JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS, "unable to create new native thread"); } THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "unable to create new native thread"); }
Thread::start(native_thread);
JVM_END |
isInterrupted
在Java中的声明如下:
private native boolean isInterrupted(boolean ClearInterrupted); |
从上面的本地方法注册可以看出,对应的实现为:
JVM_IsInterrupted |
具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:
JVM_QUICK_ENTRY(jboolean, JVM_IsInterrupted(JNIEnv* env, jobject jthread, jboolean clear_interrupted)) JVMWrapper("JVM_IsInterrupted");
// Ensure that the C++ Thread and OSThread structures aren't freed before we operate oop java_thread = JNIHandles::resolve_non_null(jthread); MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock); // We need to re-resolve the java_thread, since a GC might have happened during the // acquire of the lock JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)); if (thr == NULL) { return JNI_FALSE; } else { return (jboolean) Thread::is_interrupted(thr, clear_interrupted != 0); } JVM_END |
isAlive
在Java中的声明如下:
public final native boolean isAlive(); |
从上面的本地方法注册可以看出,对应的实现为:
JVM_IsThreadAlive |
具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:
JVM_ENTRY(jboolean, JVM_IsThreadAlive(JNIEnv* env, jobject jthread)) JVMWrapper("JVM_IsThreadAlive");
oop thread_oop = JNIHandles::resolve_non_null(jthread); return java_lang_Thread::is_alive(thread_oop); JVM_END |
countStackFrames
在Java中的声明如下:
@Deprecated public native int countStackFrames(); |
从上面的本地方法注册可以看出,对应的实现为:
JVM_CountStackFrames |
具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:
JVM_ENTRY(jint, JVM_CountStackFrames(JNIEnv* env, jobject jthread)) JVMWrapper("JVM_CountStackFrames");
// Ensure that the C++ Thread and OSThread structures aren't freed before we operate oop java_thread = JNIHandles::resolve_non_null(jthread); bool throw_illegal_thread_state = false; int count = 0;
{ MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock); // We need to re-resolve the java_thread, since a GC might have happened during the // acquire of the lock JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread));
if (thr == NULL) { // do nothing } else if(! thr->is_external_suspend() || ! thr->frame_anchor()->walkable()) { // Check whether this java thread has been suspended already. If not, throws // IllegalThreadStateException. We defer to throw that exception until // Threads_lock is released since loading exception class has to leave VM. // The correct way to test a thread is actually suspended is // wait_for_ext_suspend_completion(), but we can't call that while holding // the Threads_lock. The above tests are sufficient for our purposes // provided the walkability of the stack is stable - which it isn't // 100% but close enough for most practical purposes. throw_illegal_thread_state = true; } else { // Count all java activation, i.e., number of vframes for(vframeStream vfst(thr); !vfst.at_end(); vfst.next()) { // Native frames are not counted if (!vfst.method()->is_native()) count++; } } }
if (throw_illegal_thread_state) { THROW_MSG_0(vmSymbols::java_lang_IllegalThreadStateException(), "this thread is not suspended"); } return count; JVM_END |
holdsLock
在Java中的声明如下:
public static native boolean holdsLock(Object obj); |
从上面的本地方法注册可以看出,对应的实现为:
JVM_HoldsLock |
具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:
JVM_ENTRY(jboolean, JVM_HoldsLock(JNIEnv* env, jclass threadClass, jobject obj)) JVMWrapper("JVM_HoldsLock"); assert(THREAD->is_Java_thread(), "sanity check"); if (obj == NULL) { THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE); } Handle h_obj(THREAD, JNIHandles::resolve(obj)); return ObjectSynchronizer::current_thread_holds_lock((JavaThread*)THREAD, h_obj); JVM_END |
dumpThreads
在Java中的声明如下:
private native static StackTraceElement[][] dumpThreads(Thread[] threads); |
从上面的本地方法注册可以看出,对应的实现为:
JVM_DumpThreads |
具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:
JVM_ENTRY(jobjectArray, JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threads)) JVMWrapper("JVM_DumpThreads"); JvmtiVMObjectAllocEventCollector oam;
// Check if threads is null if (threads == NULL) { THROW_(vmSymbols::java_lang_NullPointerException(), 0); }
objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(threads)); objArrayHandle ah(THREAD, a); int num_threads = ah->length(); // check if threads is non-empty array if (num_threads == 0) { THROW_(vmSymbols::java_lang_IllegalArgumentException(), 0); }
// check if threads is not an array of objects of Thread class klassOop k = objArrayKlass::cast(ah->klass())->element_klass(); if (k != SystemDictionary::Thread_klass()) { THROW_(vmSymbols::java_lang_IllegalArgumentException(), 0); }
ResourceMark rm(THREAD);
GrowableArray<instanceHandle>* thread_handle_array = new GrowableArray<instanceHandle>(num_threads); for (int i = 0; i < num_threads; i++) { oop thread_obj = ah->obj_at(i); instanceHandle h(THREAD, (instanceOop) thread_obj); thread_handle_array->append(h); }
Handle stacktraces = ThreadService::dump_stack_traces(thread_handle_array, num_threads, CHECK_NULL); return (jobjectArray)JNIHandles::make_local(env, stacktraces());
JVM_END |
getThreads
在Java中的声明如下:
private native static Thread[] getThreads(); |
从上面的本地方法注册可以看出,对应的实现为:
JVM_GetAllThreads |
具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:
JVM_ENTRY(jobjectArray, JVM_GetAllThreads(JNIEnv *env, jclass dummy)) ResourceMark rm(THREAD); ThreadsListEnumerator tle(THREAD, false, false); JvmtiVMObjectAllocEventCollector oam;
int num_threads = tle.num_threads(); objArrayOop r = oopFactory::new_objArray(SystemDictionary::Thread_klass(), num_threads, CHECK_NULL); objArrayHandle threads_ah(THREAD, r);
for (int i = 0; i < num_threads; i++) { Handle h = tle.get_threadObj(i); threads_ah->obj_at_put(i, h()); }
return (jobjectArray) JNIHandles::make_local(env, threads_ah()); JVM_END |
setPriority0
在Java中的声明如下:
private native void setPriority0(int newPriority); |
从上面的本地方法注册可以看出,对应的实现为:
JVM_SetThreadPriority |
具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:
JVM_ENTRY(void, JVM_SetThreadPriority(JNIEnv* env, jobject jthread, jint prio)) JVMWrapper("JVM_SetThreadPriority"); // Ensure that the C++ Thread and OSThread structures aren't freed before we operate MutexLocker ml(Threads_lock); oop java_thread = JNIHandles::resolve_non_null(jthread); java_lang_Thread::set_priority(java_thread, (ThreadPriority)prio); JavaThread* thr = java_lang_Thread::thread(java_thread); if (thr != NULL) { // Thread not yet started; priority pushed down when it is Thread::set_priority(thr, (ThreadPriority)prio); } JVM_END |
stop0
在Java中的声明如下:
private native void stop0(Object o); |
从上面的本地方法注册可以看出,对应的实现为:
JVM_StopThread |
具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:
JVM_ENTRY(void, JVM_StopThread(JNIEnv* env, jobject jthread, jobject throwable)) JVMWrapper("JVM_StopThread");
oop java_throwable = JNIHandles::resolve(throwable); if (java_throwable == NULL) { THROW(vmSymbols::java_lang_NullPointerException()); } oop java_thread = JNIHandles::resolve_non_null(jthread); JavaThread* receiver = java_lang_Thread::thread(java_thread); Events::log_exception(JavaThread::current(), "JVM_StopThread thread JavaThread " INTPTR_FORMAT " as oop " INTPTR_FORMAT " [exception " INTPTR_FORMAT "]", receiver, (address)java_thread, throwable); // First check if thread is alive if (receiver != NULL) { // Check if exception is getting thrown at self (use oop equality, since the // target object might exit) if (java_thread == thread->threadObj()) { THROW_OOP(java_throwable); } else { // Enques a VM_Operation to stop all threads and then deliver the exception... Thread::send_async_exception(java_thread, JNIHandles::resolve(throwable)); } } else { // Either: // - target thread has not been started before being stopped, or // - target thread already terminated // We could read the threadStatus to determine which case it is // but that is overkill as it doesn't matter. We must set the // stillborn flag for the first case, and if the thread has already // exited setting this flag has no affect java_lang_Thread::set_stillborn(java_thread); } JVM_END |
suspend0
在Java中的声明如下:
private native void suspend0(); |
从上面的本地方法注册可以看出,对应的实现为:
JVM_SuspendThread |
具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:
JVM_ENTRY(void, JVM_SuspendThread(JNIEnv* env, jobject jthread)) JVMWrapper("JVM_SuspendThread"); oop java_thread = JNIHandles::resolve_non_null(jthread); JavaThread* receiver = java_lang_Thread::thread(java_thread);
if (receiver != NULL) { // thread has run and has not exited (still on threads list)
{ MutexLockerEx ml(receiver->SR_lock(), Mutex::_no_safepoint_check_flag); if (receiver->is_external_suspend()) { // Don't allow nested external suspend requests. We can't return // an error from this interface so just ignore the problem. return; } if (receiver->is_exiting()) { // thread is in the process of exiting return; } receiver->set_external_suspend(); }
// java_suspend() will catch threads in the process of exiting // and will ignore them. receiver->java_suspend();
// It would be nice to have the following assertion in all the // time, but it is possible for a racing resume request to have // resumed this thread right after we suspended it. Temporarily // enable this assertion if you are chasing a different kind of // bug. // // assert(java_lang_Thread::thread(receiver->threadObj()) == NULL || // receiver->is_being_ext_suspended(), "thread is not suspended"); } JVM_END |
resume0
在Java中的声明如下:
private native void resume0(); |
从上面的本地方法注册可以看出,对应的实现为:
JVM_ResumeThread |
具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:
JVM_ENTRY(void, JVM_ResumeThread(JNIEnv* env, jobject jthread)) JVMWrapper("JVM_ResumeThread"); // Ensure that the C++ Thread and OSThread structures aren't freed before we operate. // We need to *always* get the threads lock here, since this operation cannot be allowed during // a safepoint. The safepoint code relies on suspending a thread to examine its state. If other // threads randomly resumes threads, then a thread might not be suspended when the safepoint code // looks at it. MutexLocker ml(Threads_lock); JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)); if (thr != NULL) { // the thread has run and is not in the process of exiting thr->java_resume(); } JVM_END |
interrupt0
在Java中的声明如下:
private native void interrupt0(); |
从上面的本地方法注册可以看出,对应的实现为:
JVM_Interrupt |
具体的实现在\hotspot\src\share\vm\prims目录下的jvm.cpp。实现如下:
JVM_ENTRY(void, JVM_Interrupt(JNIEnv* env, jobject jthread)) JVMWrapper("JVM_Interrupt");
// Ensure that the C++ Thread and OSThread structures aren't freed before we operate oop java_thread = JNIHandles::resolve_non_null(jthread); MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock); // We need to re-resolve the java_thread, since a GC might have happened during the // acquire of the lock JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)); if (thr != NULL) { Thread::interrupt(thr); } JVM_END |
相关推荐
电子书相关:包含4个有关JAVA线程的电子书(几乎涵盖全部有关线程的书籍) OReilly.Java.Threads.3rd.Edition.Sep.2004.eBook-DDU Java Thread Programming (Sams) java线程第二版中英文 java线程第二版中英文 ...
【Java并行(4):线程安全前传之Singleton1】 在Java编程中,Singleton设计模式是一种常用的设计模式,它的主要目标是确保一个类只有一个实例,并提供一个全局访问点。在多线程环境中,实现线程安全的Singleton至关...
在Java编程语言中,线程是并发执行的任务实体,它们共享同一内存空间,但拥有独立的执行路径。本文将深入探讨两种传统的Java线程实现方式,并通过一个具体的例子来阐述如何创建和管理这些线程。 首先,我们来看第一...
2. 守护线程与用户线程:守护线程不阻碍JVM退出,而用户线程则会阻止JVM退出。 八、中断与异常处理 1. Thread.interrupt():用于中断线程,但不一定立即停止,需要在run()方法内部检查中断标志并作出相应处理。 2. ...
Java作为第一个在语言级别内置线程概念的主流编程语言,它的线程模型允许开发者直接在代码中创建和管理线程。每个Java应用程序至少包含一个主线程,由JVM创建,用于执行`main()`方法。此外,JVM还会为诸如垃圾回收、...
《JAVA线程第三版》是Java并发编程领域的一本经典著作,主要针对Java线程的深入理解和实践提供了详尽的指导。这本书详细介绍了如何在Java应用程序中有效地使用多线程,以提高程序的性能和可扩展性。Java线程是Java...
在JAVA语言程序设计中,第十四章主要探讨的是多线程这一核心概念。多线程是Java编程中不可或缺的一部分,它允许程序同时执行多个独立的任务,从而提高应用程序的效率和响应性。在Java中,多线程是通过实现Runnable...
4. 守护线程(Daemon Thread):这种线程在没有其他非守护线程运行时会自动结束,常用于后台服务,如垃圾回收器。 5. 死锁、活锁和饥饿:线程安全编程中需要避免这些问题,死锁是两个或更多线程相互等待对方释放...
java多线程每个线程挨着打印ABC的4种实现方式,有4个线程t1、t2、t3、t4,t1打印A后t2打印A再t3打印A再t4打印A,然后从新回到t1打印B再t2打印B...t4打印B... 4个线程轮流打印abc... 一个线程可以理解为一个人,打印...
"Java使用Callable和Future创建线程操作示例" Java使用Callable和Future创建线程操作示例主要介绍了Java使用Callable和Future创建线程操作,结合实例形式分析了java使用Callable接口和Future类创建线程的相关操作...
Java多线程编程是Java开发中的重要组成部分,它允许程序同时执行多个任务,提升系统效率。在Java中,实现多线程主要有两种方式:继承Thread类和实现Runnable接口。本资料"Java多线程编程核心技术.zip"深入探讨了这些...
在Java中,有两种主要的方式来实现多线程: - **继承Thread类**:创建一个新的类继承自`Thread`类,并重写其中的`run()`方法。 - **实现Runnable接口**:创建一个新的类实现`Runnable`接口,并实现`run()`方法。...
4. 等待/阻塞(Blocked/Waiting):线程可能会因为以下原因进入此状态: - 对象锁:当线程尝试获取一个已被其他线程持有的对象锁时,它会被阻塞。 - 等待条件变量:通过`wait()`方法,线程会在一个监视器上等待,...
4. **线程同步**:为了防止多线程环境中的数据竞争,Java提供了`synchronized`关键字、`wait()`, `notify()`和`notifyAll()`方法以及`java.util.concurrent`包中的工具类,如`Semaphore`和`Lock`。 5. **线程池**:...
- **Java线程的独特之处**:Java是第一个在语言级别明确包含线程支持的主流编程语言,这意味着开发者可以直接在Java代码中管理和创建线程,而不必依赖于底层操作系统的API。 #### 三、Java线程的创建与使用 - **每...
《Java语言程序设计(基础篇+进阶篇)第六版》是Java学习的重要参考资料,尤其对于初学者和希望深入理解Java编程概念的人来说,这是一本不可多得的教材。本书分为基础篇和进阶篇,涵盖了Java编程的各个方面,旨在帮助...
在Java编程语言中,线程是程序执行的基本单元,它允许程序并发地执行多个任务。本文将对Java线程类进行深入的总结,并通过思维导图帮助理解各个类之间的关系。我们将探讨`Thread`类、`Runnable`接口、线程的状态、...
Java是第一个在语言级别支持线程的主流编程语言。这一设计使得开发人员能够更容易地利用多线程的优势来提高程序性能,特别是在多处理器系统中。 #### 二、Java线程的使用场景 **2.1 提高用户界面响应速度** 在...