thread相关

Thread相关学习之六 - Thread.java中的主要方法

2019-02-20  本文已影响55人  AlanKim

Thread中的主要方法

下面开始去看下Thread中的一些方法,同时理解下这些方法对线程的状态会产生哪些影响。

currentThread
    /**
     * Returns a reference to the currently executing thread object.
     *
     * @return  the currently executing thread.
     */
    public static native Thread currentThread();

这是一个native方法,用于获取当前线程的引用

yield
    /**
     * A hint to the scheduler that the current thread is willing to yield
     * its current use of a processor. The scheduler is free to ignore this
     * hint.
     * 告诉调度器当前线程愿意让出cpu资源。但是调度器可以忽略这个hint暗示
     *
     * <p> Yield is a heuristic attempt to improve relative progression
     * between threads that would otherwise over-utilise a CPU. Its use
     * should be combined with detailed profiling and benchmarking to
     * ensure that it actually has the desired effect.
     *
     *
     * <p> It is rarely appropriate to use this method. It may be useful
     * for debugging or testing purposes, where it may help to reproduce
     * bugs due to race conditions. It may also be useful when designing
     * concurrency control constructs such as the ones in the
     * {@link java.util.concurrent.locks} package.
     */
    public static native void yield();

yield是告诉调度器,当前线程主动让出CPU.

Thread.yield(); 方法执行后,当前线程有意愿让出cpu资源,但是未必一定会让出,而状态一直是Runnable 。

测试代码

public class YieldTest {

    public static void main(String[] args){
        Thread thread = new Thread(){
            @Override
            public void run() {
                System.out.println("sub thread running");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        System.out.println("startTime=" + System.currentTimeMillis());
        thread.start();
        Thread.yield();
        System.out.println(Thread.currentThread().getName() + "," + Thread.currentThread().getState());
        System.out.println("endTime=" + System.currentTimeMillis());

    }
}

总体来看,yield方法很少会使用,了解即可。

sleep
   /**
     * Causes the currently executing thread to sleep (temporarily cease
     * execution) for the specified number of milliseconds, subject to
     * the precision and accuracy of system timers and schedulers. The thread
     * does not lose ownership of any monitors.
     *
     * @param  millis
     *         the length of time to sleep in milliseconds
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    public static native void sleep(long millis) throws InterruptedException;

很简单也很常用的一个方法,暂停当前线程,线程状态实际上为SLEEPING,不过这个SLEEPING在java线程的状态中并没有定义,而是在jvm中定义的,如下:

java_lang_thread.h中代码如下:

/*
 * Class:     java_lang_Thread
 * Method:    sleep
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_java_lang_Thread_sleep
  (JNIEnv *, jclass, jlong);

可以看到这里调用的是jnicall,还是会走到jvm.h和jvm.cpp中,直接看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);

  HOTSPOT_THREAD_SLEEP_BEGIN(millis);

  EventThreadSleep event;

  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::naked_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) {
        if (event.should_commit()) {
          event.set_time(millis);
          event.commit();
        }
        HOTSPOT_THREAD_SLEEP_END(1);

        // 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);
  }
  if (event.should_commit()) {
    event.set_time(millis);
    event.commit();
  }
  HOTSPOT_THREAD_SLEEP_END(0);
JVM_END

注意这里 thread->osthread()->set_state(SLEEPING);,也就是将线程设置成了SLEEPING状态。

而Thread.sleep 就是使当前线程变成SLEEPING状态。不过在Java中,Thread没有对应状态,而只是在jvm中thread的状态设置成了

JVMTI_THREAD_STATE_ALIVE +          
JVMTI_THREAD_STATE_WAITING +
JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT +
JVMTI_THREAD_STATE_SLEEPING,

另外注意一点,sleep的时间到期后,不一定会马上执行,只是会继续变成Runnable状态,但是还要等待cpu资源。

sleep方法并不会交出对象锁,只是让出cpu资源,其他状态都保持。

上一篇下一篇

猜你喜欢

热点阅读