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掉了的方法。
普通方法
nextThreadNum
nextThreadID
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 |
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; |
从上面的本地方法注册可以看出,对应的实现为:
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 |