`
lobin
  • 浏览: 418068 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java 第4篇: 线程

 
阅读更多

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 Threadjava.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_pointThreadFunction),第二个参数表示线程栈空间大小。

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\vmos_solaris.cpp下,其他平台在src\os\solaris\vm\os_solaris.cpphotspot\src\os\windows\vm\os_windows.cpphotspot\src\os\linux\vm\os_linux.cpphotspot\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_createstart routine,在这个函数里调用的Java Thread线程的run方法,在这里设置线程为初始状态INITIALIZED,并进入阻塞等待直到后面调用os::start_thread后才能继续运行。具体代码如下:

具体实现不同平台不一样,代码实现在hotspot\src\os\solaris\vmos_solaris.cpp下,其他平台在src\os\solaris\vm\os_solaris.cpphotspot\src\os\windows\vm\os_windows.cpphotspot\src\os\linux\vm\os_linux.cpphotspot\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\vmos_solaris.cpp下,其他平台在src\os\solaris\vm\os_solaris.cpphotspot\src\os\windows\vm\os_windows.cpphotspot\src\os\linux\vm\os_linux.cpphotspot\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();

}

 

 

JavaThreadThread的继承关系:

 

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

 

 

分享到:
评论

相关推荐

    线程 JAVA java线程 java线程第3版 java线程第2版第3版合集

    电子书相关:包含4个有关JAVA线程的电子书(几乎涵盖全部有关线程的书籍) OReilly.Java.Threads.3rd.Edition.Sep.2004.eBook-DDU Java Thread Programming (Sams) java线程第二版中英文 java线程第二版中英文 ...

    Java并行(4):线程安全前传之Singleton1

    【Java并行(4):线程安全前传之Singleton1】 在Java编程中,Singleton设计模式是一种常用的设计模式,它的主要目标是确保一个类只有一个实例,并提供一个全局访问点。在多线程环境中,实现线程安全的Singleton至关...

    java线程:两种传统的实现方式.zip

    在Java编程语言中,线程是并发执行的任务实体,它们共享同一内存空间,但拥有独立的执行路径。本文将深入探讨两种传统的Java线程实现方式,并通过一个具体的例子来阐述如何创建和管理这些线程。 首先,我们来看第一...

    java多线程详解

    Java作为第一个在语言级别内置线程概念的主流编程语言,它的线程模型允许开发者直接在代码中创建和管理线程。每个Java应用程序至少包含一个主线程,由JVM创建,用于执行`main()`方法。此外,JVM还会为诸如垃圾回收、...

    JAVA线程第三版

    《JAVA线程第三版》是Java并发编程领域的一本经典著作,主要针对Java线程的深入理解和实践提供了详尽的指导。这本书详细介绍了如何在Java应用程序中有效地使用多线程,以提高程序的性能和可扩展性。Java线程是Java...

    JAVA语言程序设计-第十四章 多线程

    在JAVA语言程序设计中,第十四章主要探讨的是多线程这一核心概念。多线程是Java编程中不可或缺的一部分,它允许程序同时执行多个独立的任务,从而提高应用程序的效率和响应性。在Java中,多线程是通过实现Runnable...

    【JAVA多线程】多线程编程核心技术学习资料

    4. 守护线程(Daemon Thread):这种线程在没有其他非守护线程运行时会自动结束,常用于后台服务,如垃圾回收器。 5. 死锁、活锁和饥饿:线程安全编程中需要避免这些问题,死锁是两个或更多线程相互等待对方释放...

    java多线程每个线程挨着打印ABC的4种实现方式

    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使用Callable接口和Future类创建线程的相关操作...

    Java多线程编程核心技术.zip

    Java多线程编程是Java开发中的重要组成部分,它允许程序同时执行多个任务,提升系统效率。在Java中,实现多线程主要有两种方式:继承Thread类和实现Runnable接口。本资料"Java多线程编程核心技术.zip"深入探讨了这些...

    JAVA网络编程及多线程

    在Java中,有两种主要的方式来实现多线程: - **继承Thread类**:创建一个新的类继承自`Thread`类,并重写其中的`run()`方法。 - **实现Runnable接口**:创建一个新的类实现`Runnable`接口,并实现`run()`方法。...

    JAVA程序设计:第13章 线程.ppt

    4. 等待/阻塞(Blocked/Waiting):线程可能会因为以下原因进入此状态: - 对象锁:当线程尝试获取一个已被其他线程持有的对象锁时,它会被阻塞。 - 等待条件变量:通过`wait()`方法,线程会在一个监视器上等待,...

    Java数组,Java数组,多线程编程

    4. **线程同步**:为了防止多线程环境中的数据竞争,Java提供了`synchronized`关键字、`wait()`, `notify()`和`notifyAll()`方法以及`java.util.concurrent`包中的工具类,如`Semaphore`和`Lock`。 5. **线程池**:...

    Java线程入门

    - **Java线程的独特之处**:Java是第一个在语言级别明确包含线程支持的主流编程语言,这意味着开发者可以直接在Java代码中管理和创建线程,而不必依赖于底层操作系统的API。 #### 三、Java线程的创建与使用 - **每...

    Java语言程序设计(基础篇+进阶篇)第六版 答案(不含编程题)

    《Java语言程序设计(基础篇+进阶篇)第六版》是Java学习的重要参考资料,尤其对于初学者和希望深入理解Java编程概念的人来说,这是一本不可多得的教材。本书分为基础篇和进阶篇,涵盖了Java编程的各个方面,旨在帮助...

    Java线程类小结(附思维导图)

    在Java编程语言中,线程是程序执行的基本单元,它允许程序并发地执行多个任务。本文将对Java线程类进行深入的总结,并通过思维导图帮助理解各个类之间的关系。我们将探讨`Thread`类、`Runnable`接口、线程的状态、...

    秒杀多线程第十六篇 多线程十大经典案例之一 双线程读写队列数据

    在《秒杀多线程系列》的前十五篇中介绍多线程的相关概念,多线程同步互斥问题《秒杀多线程第四篇一个经典的多线程同步问题》及解决多线程同步互斥的常用方法——关键段、事件、互斥量、信号量、读写锁。为了让大家...

    java 猜数字游戏,学习线程

    - 随机数生成线程:使用`Random`类生成一个指定范围内的随机整数,并将其存储在一个全局变量中,如`volatile`修饰的`int`类型变量,以确保线程可见性。 - 猜测线程:不断接收用户输入,与随机数进行比较,判断是否...

Global site tag (gtag.js) - Google Analytics