美文网首页thread相关
Thread相关学习之六 - Thread.java中的主要方法

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

作者: AlanKim | 来源:发表于2019-02-20 00:29 被阅读55次

    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资源,其他状态都保持。

    相关文章

      网友评论

        本文标题:Thread相关学习之六 - Thread.java中的主要方法

        本文链接:https://www.haomeiwen.com/subject/ysnksqtx.html